книга -
"Assembler", Виктор Юров, издательство "Питер"
(к ней, кстати, есть ещё две книги -
"Assembler. Специальный справочник" и
"Assembler. Практикум")
:arrow:
оказалось не так уж всё и сложно, как мне самому вначале показалось, хотя некоторый груз наблюдается
. Но говорить придётся не только про
префиксы повторения rep и иже, а про
цепочечные команды.
этих команд семь. Принцип работы одинаков и для работающих с 8-битными числами, и с 16 и 32. Мнемоники этих команд отличаются только символом на конце - "b", "w" или "d".
(например: movsb, movsw, movsd)
вот эти команды:
1: movs [i(адрес_приёмника,адрес_источника[/i(
2: cpms [i(адрес_приёмника,адрес_источника[/i(
3: scas [i(адрес_приёмника[/i(
4: lods [i(адрес_источника[/i(
5: stos [i(адрес_приёмника[/i(
6: ins [i(адрес_приёмника,номер_порта[/i(
7: outs [i(номер_порта,адрес_источника[/i(
адрес_приёмника - пара es:di
адрес_источника - пара ds:si (не только ds, но сейчас это неважно)
сама по себе цепочечная команда (без префикса) выполняется один раз:
movsb ad2,ad1 ;пересылает байт
Если у мнемокоманды добавлен в конце символ "b", "w" или "d", то операнды "адрес_приёмника, адрес_источника" указывать в мнемокоманде не обязательно, так как они используются компилятором лишь для определения типа элементов цепочки.
Это связано с тем, что адреса формирутся в регистрах es:di и ds:si, и перед выполнением цепочечных команд программист должен обеспечить правильную настройку этих регистров на нужные адреса.
поэтому
movs ad2,ad1
будет эквивалентно
movsb
при правильной настройке es:di и ds:si.
_____________________________________________________________
если в поле метки поставить префикс, то цепочечная команда будет повторно выполняться до тех пор, пока не будет достигнуто условие, отслеживаемое префиксом. Пример установки префикса:
rep movsb ad2,ad1 ;пересылает строку байт (в общем случае)
Префиксов всего три:
1) rep
2) repz или repe
3) repnz или repne
1) rep - заставляет цепочечную команду выполняться до тех пор, пока содержимое регистра cx не равно нулю.
алгоритм работы rep следующий:
1. проверяет cx - если cx равен нулю, то прекращает выполнение цикла и переходит к выполнению команды, следующей за цепочечной командой
2. иначе (если cx<>0 ) выполняет один раз цепочечную команду (при этом - сдвигаются адреса источников и приёмников в соответствии с работой самих цеп.команд), затем уменьшает на единицу регистр cx
3. переходит к выполнению шага 1.
2) repz - заставляет цепочечную команду выполняться до тех пор, пока содержимое регистра cx не равно нулю или флаг нуля zf равен 1 (установлен).
алгоритм работы repz следующий:
1. если cx равен нулю и флаг zf равен нулю (сброшен), то прекращает выполнение цикла и переходит к выполнению команды, следующей за цепочечной командой
2. иначе (если cx<>0 или zf==1) выполняет один раз цепочечную команду (при этом - сдвигаются адреса источников и приёмников в соответствии с работой самих цеп.команд), затем уменьшает на единицу регистр cx
3. переходит к выполнению шага 1.
3) repnz - заставляет цепочечную команду выполняться до тех пор, пока содержимое регистра cx не равно нулю или флаг нуля zf равен 0 (сброшен).
алгоритм работы repz следующий:
1. если cx равен нулю и флаг zf равен 1 (установлен), то прекращает выполнение цикла и переходит к выполнению команды, следующей за цепочечной командой
2. иначе (если cx<>0 или zf==0) выполняет один раз цепочечную команду (при этом - сдвигаются адреса источников и приёмников в соответствии с работой самих цеп.команд), затем уменьшает на единицу регистр cx
3. переходит к выполнению шага 1.