Приемы уменьшения размера ассемблерного кода |
1. Заголовок или название темы должно быть информативным
2. Все тексты программ должны помещаться в теги [CODE=asm] [/CODE]
3. Прежде чем задавать вопрос, см. "FAQ",если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно, такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Ассемблера. Исключение только с согласия модератора.
5. НЕ используйте форум для личного общения! Все, что не относиться к обсуждению темы - на PM!
6. Проверяйте программы перед тем, как выложить их на форум!!
Приемы уменьшения размера ассемблерного кода |
xds |
6.08.2004 1:46
Сообщение
#1
|
N337 Группа: Пользователи Сообщений: 737 Пол: Мужской Репутация: 26 |
Несколько примеров под 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] где a - bx,bp или константа; b - si, di или константа; r - любой регистр общего назначения. Примечание: кстати, многие ассемблеры автоматически заменяют "lea r,label" на "mov r,offset label" исходя из соображений, что настоящая инструкция "lea" в данном случае займет 4 байта, а "mov" - только 3. (4) Загрузка константы в сегментный регистр: mov ax,0A000h ; -> push 0A000h Примечание: "push <константа>" появилась в системе команд x86 начиная с I80186. (5) Получение адреса элемента массива по его индексу: mov ax,ELEM_SIZE ; -> mov ax,ELEM_SIZE где ELEM_SIZE - размер элемента массива, index (регистр общего назначения или переменная в памяти) - индекс элемента, адрес которого нас интересует. (6) Для особо ярых поклонников x86 и команд push/pop: Если на входе в процедуру (или другой участок кода, от которого требуется сохранять, а затем восстанавливать значения некоторых регистров) сохраняется больше одного регистра, то последовательность "push"'ей можно заменить на "pusha", а "pop"'ов - на команду со звучным названием "popa". Примечание: кстати, RISC-процессор SPARC при обращении к процедурам в большинстве случаев прекрасно обходится без технологии "толкай-тяни" благодаря использованию регистрового файла со скользящим окном, который в частности выполняет функции стека вызовов - в нем сохраняются адреса возврата, передаются параметры и хранятся локальные переменные. May be continued... ;) P.S. В дополнение - маленький пример, как это работает... Прикрепленные файлы flag.zip ( 1.44 килобайт ) Кол-во скачиваний: 236 -------------------- The idiots are winning.
|
Анна |
28.09.2004 23:29
Сообщение
#2
|
Гость |
...ещё достигается хорошая оптимизация при применении вместо команд обычного умножения(деления) сдвигов -оч хорошие результаты :p2:
Сообщение отредактировано: Анна - 28.09.2004 23:35 |
Shadow |
28.09.2004 23:36
Сообщение
#3
|
Lonely_Raven Группа: Пользователи Сообщений: 640 Пол: Мужской Репутация: 1 |
Анна
на степени двойки -------------------- Программа делает то что вы ей приказали а не то что бы ВАМ хотелось бы.
МЕРФИ --------------------- RTFM - Read the fucking manual --------------------- http://www.livejournal.com/users/lonley_raven/ |
P@sh@ |
29.09.2004 10:23
Сообщение
#4
|
Бывалый Группа: Пользователи Сообщений: 180 Пол: Мужской Репутация: 2 |
Я еще со времен ПК8000 (на проце К580) задумывался, а почему не сделали вместо команд условного перехода типа JNZ, JZ, JC и т.д. просто условия (в виде префиксов например): IFNZ <команда> - мне кажется, так было бы удобнее, так как частенько условие нужно лишь для выполнения одной команды (только представьте: IFNZ DEC AX), а из-за этого приходится делать переход... а переходы по условию выглядели бы так: IFZ JMP adr. Однако так никто никогда не делал, из чего я заключаю, что это гораздо сложнее сделать при существующих архитектурах процессоров? (другой вариант - никто не догадался ;) ) С другой стороны - есть же префиксы-циклы REPNZ и т.д.
|
xds |
29.09.2004 16:20
Сообщение
#5
|
N337 Группа: Пользователи Сообщений: 737 Пол: Мужской Репутация: 26 |
К счастью, все не так уж плохо. В некоторых архитектурах встречаются инструкции условного пропуска следующих за ними инструкций. Так в 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-архитектуры легко справляются с проблемами "накопления совместимости" путем разумного использования исключений для программной эмуляции устаревших инструкций. -------------------- The idiots are winning.
|
Atos |
30.09.2004 12:13
Сообщение
#6
|
Прогрессор Группа: Модераторы Сообщений: 602 Пол: Мужской Реальное имя: Михаил Репутация: 9 |
Вместо команды mov ax, 0 ,занимающей в памяти 5 байт, можно написать xor ax, ax , занимающую 1 байт. Хотя, это, наверное, общеизвестный факт, или нет? {Нам на лекции рассказали}
|
xds |
30.09.2004 14:16
Сообщение
#7
|
N337 Группа: Пользователи Сообщений: 737 Пол: Мужской Репутация: 26 |
Цитата(Atos @ 30.09.04 12:13) Вместо команды mov ax, 0 ,занимающей в памяти 5 байт В x86/real mode - 3 байта... -------------------- The idiots are winning.
|
xds |
30.09.2004 15:15
Сообщение
#8
|
N337 Группа: Пользователи Сообщений: 737 Пол: Мужской Репутация: 26 |
Существует на удивление много способов применения инструкций cbw/cwd "не по прямому назначению". Вот как, например, можно посчитать абсолютную величину 16-битного целого без применения команд условного перехода. Пусть в ax - исходное число, тогда
cwd или cwd возвратит в ax его абсолютную величину. В основе подобных ухищрений лежит простое свойство этих команд возвращать 0 для положительных чисел и -1 - для отрицательных. Вот как можно реализовать аналог предложения Паскаля "if x < 0 then x := 0;": mov ax,x "if x >= 320 then x := 0;": mov ax,x -------------------- The idiots are winning.
|
P@sh@ |
1.10.2004 8:09
Сообщение
#9
|
Бывалый Группа: Пользователи Сообщений: 180 Пол: Мужской Репутация: 2 |
xds
но ведь щас вроде как везде RISC-архитектура используется... я помню, первый раз увидел это слово (аббревиатуру) в описании первых AMD-процессоров... интересно, а можно программировать напрямую на микрокоде, в обход "интерпретатора" команд х86 ? |
xds |
5.10.2004 14:28
Сообщение
#10
|
N337 Группа: Пользователи Сообщений: 737 Пол: Мужской Репутация: 26 |
Цитата(P@sh@ @ 1.10.04 8:09) но ведь щас вроде как везде RISC-архитектура используется... Я имел в виду полноценные RISC-процессоры (SPARC, MIPS, PA-RISC, AVR и т. п.), т. е. те, у которых RISC-архитектура реализована на уровне системы команд - собственно там, где её польза действительно ощутима. -------------------- The idiots are winning.
|
Текстовая версия | 27.04.2024 10:03 |