Страница: 1 |
Страница: 1 |
Вопрос: Когда нехватает регистров...
Добавлено: 25.05.05 08:54
Автор вопроса: RomK aka Куций
Я ASMатик-самоучка и поэтому прошу ногами сразу не бить и кирпичи не кидать :)
Как-то раз я решил оптимизировать программу, написаную на PowerBasic, т.е. повставлять в код вставки ASM. И столкнулся с такой проблемой, что регистров EAX, EBX, EDX (ECX - у меня счётчик) мне не хватило...
Почти все переменные типа Long, поэтому воспользоваться отдельно частями регистров не удастся.
Внимание вопросы:
1. Можно ли так писать (если компилятор не выдаёт ошибок)?
Dim a&, b& ' Это всего-лишь пример
a = 20
b = 30
! add a, b
MsgBox Str$(a)
2. И сравниться оно по быстродействию с таким:
Dim temp&
! mov eax, 20
! mov ebx, 30
! add eax, ebx
! mov temp, eax
MsgBox Str$(temp)
Ответы
Всего ответов: 8
Номер ответа: 1
Автор ответа:
HOOLIGAN
Вопросов: 0
Ответов: 1066
Профиль | | #1
Добавлено: 25.05.05 09:46
Компилятор как раз выдаcт ошибку на строке
! add a, b
потому, что непосредственно сложения двух m32 нет в ассемблере. Есть сложение m32 c imm32:
! add a,30
Dim temp&
! mov eax, 20
! add eax, 30
! mov temp, eax
MsgBox Str$(temp)
А вообще это всё проверяется элементарным набором этих нескольких строк и последующей компиляцией.
Номер ответа: 2
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #2
Добавлено: 25.05.05 11:48
Всё зависит от сложности алгоритма и универсального для всех ситуаци нет. Обычное сложение двух чисел в ЯВУ не показатель. Компилятор транслирует под конкретный алгоритм и сам распределяет как эффективно использовать регистры и память. Наиболее часто употребляемы значения лучше всего хранить в регистрах и скидывать в память по завершении работы алгоритма.
(ECX - у меня счётчик)
А что это ещё может быть?
Буква "C" в имени регистра является сокращением английского слова Counter (счётчик).
Номер ответа: 3
Автор ответа:
mc-black
ICQ: 308-534-060
Вопросов: 20
Ответов: 1860
Web-сайт:
Профиль | | #3
Добавлено: 25.05.05 12:24
ECX регистр общего назначения
Номер ответа: 4
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #4
Добавлено: 25.05.05 15:20
Кстати, а ESI и EDI почему не пользуешся? Заняты?
ESP и EBP тоже можно задействовать. Правда их нужно предварительно сохранить и по окончании работы восстановить. Ну и не использовать локальную память до восстановления.
Номер ответа: 5
Автор ответа:
RomK aka Куций
Вопросов: 6
Ответов: 13
Профиль | | #5
Добавлено: 26.05.05 08:24
HOOLIGAN, не понимаю почему это PB выдаст ошибку на строке
У меня почему-то всё в порядке.
И что это m32?
mc-black, ECX - регистр общего назначения, это понятно, но как ты без него к примеру цикл напишешь?
CyRax, спасибо что напомнил о ESI, EDI, ESP, EBP; теперь переменных вполне хватит. Вот только ты пишешь, что их нужно сохранить, КУДА?
Номер ответа: 6
Автор ответа:
HOOLIGAN
Вопросов: 0
Ответов: 1066
Профиль | | #6
Добавлено: 26.05.05 09:37
Он не выдаст ошибку, он её выдаёт "Assembler syntax error". Потому что не бывает такой инструкции процессора, которая непосредственно пересылала бы из памяти в память. И не может быть у тебя ничего в порядке.
Если нужно скопировать из одной ячейки памяти в другую число размером dword, то либо через регистр, либо можно воспользоваться способом, не затрагивающим регистры - через стек, но так чуть медленнее:
pop dword ptr [esp+4] ' aдрес ячейки b - в esp+4
непосредственно "pop a" компилятор РВ тоже не позволяет. Опять же выдаёт эту ошибку. На сей раз это заскок самого компилятора.
Вообще-то изучать ассемблер пользуясь убожеством PB - дело неблагодарное Возьми нормальный ассемблер (masm или fasm) и изучай.
Цикл можно написать не только с ecx. Можно в качестве переменной цикла (счётчика) использовать любой регистр или ячейку памяти. Достаточно, чтобы с ними можно было делать inc/add или dec/sub.
Но если для цикла используется JCXZ/JECXZ или LOOP, то они рассчитаны на ecx, и без ecx не обойтись.
Пример цикла без есх:
!mov a, 10
start:
!'тут тело цикла
!'тут тело цикла
!dec a
!jnz start
В данном случае переменной цикла будет "а" (dword ptr [esp+...]) А регистр ecx свободен и может использоваться для каких-нибудь других целей.
esi, edi обычно сохраняют в стеке - push esi (push edi) (при завершении их использования вернуть их прежнее состояние pop edi - pop esi). Можно изобрести экзотический вариант, и сохранять их в любой локальной или глобальной переменной, отведя эту переменную специально для хранения esi.
Регистры ebp и esp лучше пока не трогай На данной стадии ты можешь с ними не совладать.
Номер ответа: 7
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #7
Добавлено: 26.05.05 11:07
Про ESP и EBP я несколько поторопился. Одновременно их использовать не получится т.к. где то нужно помнить текущий указатель стека иначе просто не сможешь выйти из процедуры.
ESI и EDI сохранять не нужно, т.к. PB это делает сам. Относись к ним так же как и к остальным РОН, только что они на 4 части не делятся. Предпочтительно их использовать при строковых манипуляциях (или любых других повторяющихся цепочках), но это не обязательно.
К примеру цикл через ESI (именно так компилятор PB делает пустой цикл)
Lbl1:
! MOV ESI,10
! DEC ESI
! JNZ LBL1
Номер ответа: 8
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #8
Добавлено: 26.05.05 11:11
HOOLIGAN, не понимаю почему это PB выдаст ошибку на строке
! mov a, b
У меня почему-то всё в порядке.
И что это m32?
Вот это то и плохо что всё в порядка. Попробуй в начале процедуры отключить использование регистров в локальных переменных директивой #REGISTER NONE.