Оптимизация программ на ассемблереРэй Дункан Несмотря на все более широкое распространение языков програм- ¦ Чтобы ваши программы на ассемблере принесли максимум пользы, ¦
1. Оптимизация по быстродействию. Если вы пришли к выводу, что ваша программа работает недоста- числители, как процессоры 80386 или 80486, так что постарайтесь - Замещение универсальных инструкций на учитывающие конкрет- - Уменьшение количества передач в программе: за счет преобра- - Оптимизация циклов, в том числе перемещение вычислений не - Максимальное использование всех доступных регистров, за - Использование специфических для данного процессора инструк- В процессорах 80x86, но не 80x88, вам, возможно, также удаст- +--------------------------------------------------------------+
2. Оптимизация по размеру. Если работоспособность вашей программы ограничена ее разме- +--------------------------------------------------------------+
3. А стоит ли оптимизировать? Оптимизация кодов на любом языке всегда требует идти на комп- - Сокращение потребного объема памяти за счет снижения быст- - Повышение быстродействия за счет ухудшения возможностей - Сокращение времени исполнения программы за счет увеличения Все это кажется очевидным, но в большинстве реальных ситуаций xchg ax,dx В процессорах 80x86 и 80x88 команда MOV занимает 2 байта и +--------------------------------------------------------------+
4. Отказ от универсальности. Операции умножения и деления требуют немалых усилий от почти mov ax,MyVar В процессорах 8086 и 8088 эта программа может быть преобразо- mov ax,MyVar или даже в такую: shl MyVar,1 Если требуется сдвиг на одну или две позиции, то обычно проще mov ax,MyVar А в процессорах 80186, 80188, 80286, 80386 и 80486 имеется shl MyVar,3 Если вам требуется умножать на степень двойки числа длиной shl ax,1 Творчески сочетая сдвиги и сложения, можно организовать быст- mov bx,ax Использование отказа от универсальности для деления несколько shr ax,1 а для процессоров 80186, 80188, 80286, 80386 и 80486 можно вмес- shr ax,2 Нахождение остатка от деления числа без знака на 4 произво- and ax,0003h не правда ли слишком просто! sar ax,1 или для процессоров 80186, 80188, 80286, 80386 и 80486: sar ax,2 Единственная разница между командой логического (без знака) sar dx,1 Но, в отличие от операции умножения, использование сдвигов shr ax,1 Теперь, когда вы увидели этот нетривиальный прием, у вас на-
5. Оптимизация переходов и вызовов подпрограмм. Макаронные программы, изобилующие ветвлениями и переходами во cmp Balance,0 Аналогично, если разные значения некой переменной инициируют cmp ax,High Если требуется произвести сравнения с многими значениями, Table dw Routine_00 Есть еще две методики оптимизации, связанные с переходами и Proc1 proc near Proc2 proc near преобразуется в более быструю: Proc1 proc near Proc2 proc near Такая оптимизация приводит к следующему: поскольку адрес ко- Proc1 proc near может быть преобразована в: Proc1 proc near Такая рекурсивная программа часто может быть еще оптимизиро-
6. Оптимизация циклов. Литература о компиляторах переполнена обсуждением методов оп- - Никогда не делайте в цикле ничего такого, что можно сделать - Везде, где это возможно, избавляйтесь от передач управления Первое из правил следует из старинной истины, гласящей, что Items equ 100 Array dw Items dup(?) xor cx,cx Упростив этот цикл, мы получим: Items equ 100 Array dw Items dup(?) xor ax,ax После того как вы оптимизировали содержимое цикла насколько mov cx,100 часто можно сделать один: mov cx,100 Другой способ избавиться от циклов - "размотать" их, т.е. mov cx,3 можно переписать так: add ax,[bx] или даже так: add ax,[bx+0] "Разматывание" циклов - классический пример повышения быстро- mov cx,3 В приведенной последовательности имеется цикл, хотя и неяв- Lab1: movsw При работе на некоторых процессорах фирмы Intel и при неболь- movsw Но это один из случаев, когда требуется выяснить, насколько ¦ Если из цикла производится обращение к внешним устройствам, ¦ Мы уже отмечали, что почти всегда бывает целесообразно пере- Table label word Подготовив такую таблицу, мы без особых затруднений можем Sine proc near Для дополнительного ускорения работы своей программы мы можем Рис. 1. Исходный текст модуля, содержащего подпрограммы для це- title ITRIG - Integer Trig Lookup name ITRIG Table label word codeseg public Cosine ; Trig proc near ; Cosine proc near ; Sine proc near end Иногда управляющие таблицы можно весьма эффективно использо- Table label byte И снова, чтобы еще более повысить быстродействие, можно офор-
8. Оптимизация для конкретных моделей процессоров. Если ваша программа будет работать на компьютерах с конкрет- - Линейные и циклические сдвиги с непосредственным аргумен- - Команда PUSH с непосредственным операндом. - Команды ввода и вывода символьных строк. - Команды обмена со стеком содержимым всех регистров - PUSHA - Команды ENTER и LEAVE для выделения и освобождения кадра - Команды проверки соблюдения границ массива BOUND. - Команды умножения числа на непосредственный операнд. Если ваша программа будет исполняться только на компьютерах с - 32-разрядных регистров (но пользоваться ими следует с осто- - Команд пересылки с распространением нуля или знакового бита - 64-разрядных сдвигов (в сдвоенных регистрах) - команды SHLD - Установки в байте значений "истина" или "ложь" в зависимос- - Команд проверки, установки, сброса, инвертирования и прос- - Обобщенной индексной адресации и режимов адресации с масш- - Быстрого умножения при помощи команды LEA с использованием - "Дальних" условных переходов. - Перемножения 32-разрядных чисел и деления 64-разрядного - Дополнительных сегментных регистров (FS и GS). - Команд загрузки сегментных регистров SS, FS и GS (LSS, LFS Естественно, выжать максимум из архитектуры 80386 или 80486 - Изменение порядка расположения четырех байтов в 32-разряд- - Сравнение и обмен (CMPXCHG). - Обмен и сложение (XADD). Вместе с тем длительность команд, выраженная в числе тактов, |