Помощь - Поиск - Пользователи - Календарь
Полная версия: Приемы уменьшения размера ассемблерного кода
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ассемблер
xds
Несколько примеров под x86/real mode...

Примечание: далее под словосочетанием "регистр общего назначения" подразумевается один из регистров: ax, bx, cx, dx, si, di, sp, bp.

(1) Классика:
mov r,0 ; -> xor r,r

где r - регистр общего назначения;

Примечание: "бородатый" прием, получивший распространение в том или ином виде на многих архитектурах; в AVR он даже заслужил дополнительную мнемонику - "clr".

(2)
mov d,s ; -> xchg d,s

где d, s - регистры общего назначения;
замена применима в том случае, если значением s можно пожертвовать.

Примечание: на младших членах семейства x86 (I8088/I8086) инструкция "xchg" выполняется медленнее "mov".

(3)
mov r,a ; -> lea d,[a+b]
add r,b |

где
a - bx,bp или константа;
b - si, di или константа;
r - любой регистр общего назначения.

Примечание: кстати, многие ассемблеры автоматически заменяют "lea r,label" на "mov r,offset label" исходя из соображений, что настоящая инструкция "lea" в данном случае займет 4 байта, а "mov" - только 3.

(4) Загрузка константы в сегментный регистр:
mov ax,0A000h ; -> push 0A000h
mov es,ax     ;   pop es


Примечание: "push <константа>" появилась в системе команд x86 начиная с I80186.

(5) Получение адреса элемента массива по его индексу:
mov ax,ELEM_SIZE ; -> mov ax,ELEM_SIZE
mul index        ;   mul index
lea di,array     ;   add ax,offset array
add di,ax        ;   xchg di,ax

где
ELEM_SIZE - размер элемента массива,
index (регистр общего назначения или переменная в памяти) - индекс элемента, адрес которого нас интересует.

(6) Для особо ярых поклонников x86 и команд push/pop:
Если на входе в процедуру (или другой участок кода, от которого требуется сохранять, а затем восстанавливать значения некоторых регистров) сохраняется больше одного регистра, то последовательность "push"'ей можно заменить на "pusha", а "pop"'ов - на команду со звучным названием "popa".

Примечание: кстати, RISC-процессор SPARC при обращении к процедурам в большинстве случаев прекрасно обходится без технологии "толкай-тяни" благодаря использованию регистрового файла со скользящим окном, который в частности выполняет функции стека вызовов - в нем сохраняются адреса возврата, передаются параметры и хранятся локальные переменные.

May be continued... ;)

P.S. В дополнение - маленький пример, как это работает...
Анна
...ещё достигается хорошая оптимизация при применении вместо команд обычного умножения(деления) сдвигов -оч хорошие результаты :p2:
Shadow
Анна
на степени двойки
P@sh@
Я еще со времен ПК8000 (на проце К580) задумывался, а почему не сделали вместо команд условного перехода типа JNZ, JZ, JC и т.д. просто условия (в виде префиксов например): IFNZ <команда> - мне кажется, так было бы удобнее, так как частенько условие нужно лишь для выполнения одной команды (только представьте: IFNZ DEC AX), а из-за этого приходится делать переход... а переходы по условию выглядели бы так: IFZ JMP adr. Однако так никто никогда не делал, из чего я заключаю, что это гораздо сложнее сделать при существующих архитектурах процессоров? (другой вариант - никто не догадался ;) ) С другой стороны - есть же префиксы-циклы REPNZ и т.д. unsure.gif
xds
К счастью, все не так уж плохо. В некоторых архитектурах встречаются инструкции условного пропуска следующих за ними инструкций. Так в AVR RISC это команды SBIC/SBIS (Skip if Bit in I/O register is Cleared/Set) и SBRC/SBRS (Skip if Bit in Register is Cleared/Set). Следует отметить, что в AVR слово состояния процессора доступно как регистр ввода/вывода, поэтому эта архитектура является реально существующей реализацией рассмотренного тобой случая.

Впрочем, архитектуры с ортогональной системой команд (в основном RISC-процессоры и их RISC-подобные предшественники, exempli gratia, LSI-11) всегда отличались ощутимо большей долей рациональности, чем классические CISC-семейства - постепенно распухающие от объема устаревших инструкций и сгибающиеся под весом новых (в "родимом" x86 легко обнаруживаются следы i8080, и даже i8008, не говоря уж о том, что Pentium 4 до сих пор полноценно поддерживает 16-битный реальный режим). К слову, RISC-архитектуры легко справляются с проблемами "накопления совместимости" путем разумного использования исключений для программной эмуляции устаревших инструкций.
Atos
Вместо команды mov ax, 0 ,занимающей в памяти 5 байт, можно написать xor ax, ax , занимающую 1 байт. Хотя, это, наверное, общеизвестный факт, или нет? {Нам на лекции рассказали}
xds
Цитата(Atos @ 30.09.04 12:13)
Вместо команды mov ax, 0 ,занимающей в памяти 5 байт

В x86/real mode - 3 байта...
xds
Существует на удивление много способов применения инструкций cbw/cwd "не по прямому назначению". Вот как, например, можно посчитать абсолютную величину 16-битного целого без применения команд условного перехода. Пусть в ax - исходное число, тогда
        cwd
       or dx,1
       mul dx

или
        cwd
       xor ax,dx
       sub ax,dx

возвратит в ax его абсолютную величину. В основе подобных ухищрений лежит простое свойство этих команд возвращать 0 для положительных чисел и -1 - для отрицательных. Вот как можно реализовать аналог предложения Паскаля "if x < 0 then x := 0;":
        mov ax,x
       cwd
       not dx
       and ax,dx
       mov x,ax


"if x >= 320 then x := 0;":
        mov ax,x
       sub ax,320
       cwd
       and ax,dx
       and dx,320
       add ax,dx
       mov x,ax
P@sh@
xds
но ведь щас вроде как везде RISC-архитектура используется... я помню, первый раз увидел это слово (аббревиатуру) в описании первых AMD-процессоров... интересно, а можно программировать напрямую на микрокоде, в обход "интерпретатора" команд х86 ?
xds
Цитата(P@sh@ @ 1.10.04 8:09)
но ведь щас вроде как везде RISC-архитектура используется...

Я имел в виду полноценные RISC-процессоры (SPARC, MIPS, PA-RISC, AVR и т. п.), т. е. те, у которых RISC-архитектура реализована на уровне системы команд - собственно там, где её польза действительно ощутима.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.