    Этот код имеет два очевидных недостатка. Во-первых, целое п (размещенное в 
стеке по смещению Ьр+4) записывается в регистр Ьх и тут же в ах. Почему бы не 
переслать п непосредственно в регистр ах? Во-вторых, инструкция jmp 
бессмысленно переходит к следующему же адресу, якобы пропуская код, который, 
возможно, существовал бы в этом месте при других обстоятельствах. 
    Скомпилированный код изобилует подобными недостатками, кажущимися, на 
первый взгляд, грубыми ошибками, которые компетентный программист, пишущий на 
ассемблере, никогда бы не допустил. Однако имейте в виду, что если функция 
MySquare() не обладает статусом критической, эти расточительные инструкции, 
вероятно, не оказывают ощутимого влияния на быстродействие программы. 
    С другой стороны, если функция MySquare() занимает большую часть общего 
времени выполнения программы, оптимизация функции для достижения максимальной 
производительности даст приличный выигрыш. Руководствуясь ассемблерным кодом, 
сгенерированным компилятором, вы можете переписать функцию с использованием 
операторов asm, как показано в листинге 17.4. 

    Листинг 17.4.  INLINE.CPP (оптимизация функции MySquare() с помоцыо 
операторов asm) 

    1:   #include <stdio.h> 
    2: 
    3:   int MySquare(int n); 
    4: 
    5:   main() 
    6:   { 
    7:     int i; 
    8:     int array[10]; 
    9: 
   10:     for (i = 0;  i < 10;  i++) 
   11:       array[i] = MySquare(i); 
   12:     for (i = 0;   i < 10;  i++) 
   13:        printf("array[%d] == %d\n",  i,  array[i]); 
   14:     return 0; 
   15:   } 
   16: 
   17:   // Предотвращение предупреждения "Function should return value" 
   18:  #pragma warn -rvl 
   19: 
   20:   int MySquare(int n) 
   21:   { 
   22:   /* 
   23:     return n * n; 
   24:   */ 
   25:    asm { 
   26:       mov ax, word ptr n 
   27:       imul bx 
   28:     } 
   29:   } 
   30: 
   31:   // Восстановление предыдущего состояния предупреждения 
   32:   #pragma warn +rvl 

    В строках 22-24 первоначальный оператор умножения заключен в скобки 
комментария. При оптимизации ваших собственных функций никогда не удаляйте 
первоначальный код. Когда-нибудь в будущем вам может понадобиться перенести 
программу на другую компьютерную систему, которая, возможно, не будет оснащена 
процессором 80x86. В этом случае вы просто удалите скобки комментария и 
операторы asm для преобразования программы обратно в С или C++. 
    В строках 25-29 приводится оптимизированное тело функции на ассемблере. 
Первый оператор пересылает параметр а в регистр ах. Вам не надо самим 
вычислять смещения (имеется в виду использование адресных выражений наподобие 
[Ьр+4]). Вы можете сослаться на любой параметр по имени переменной, и ВASM 
вставит соответствующий адрес. 
    В строке 28 регистр ах умножается на Ьх, результат этой операции (и 
функции в целом) хранится в регистрах dx (старшее слово) и ах (младшее слово). 
Очевидно, поскольку модифицированная функция не выполняет возврат явным 
образом, излишняя инструкция jmp также уничтожается. 
    К несчастью, компилятор теперь выдает предупреждение, что в функции 
MySquare() отсутствует оператор return. Несмотря на безобидность, появление 
этого предупреждения раздражает, и вы можете его выключить с помощью директивы 
#pragma warn, как показано в строке 18. Директива 

    #pragma warn -rvl 

выключает предупреждение, а директива 

    #pragma warn +rvl 


    Глава 17. Оптимизация с помощью ассемблера     445 
