assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 52
Текст из файла (страница 52)
Команда JCXZ выполняет здесь две функции: предотвращает выполнение«пустого» цикла (когда счетчик цикла в СХ равен нулю) и отслеживает окончаниецикла после обработки всех элементов поля mas. Команда DEC после каждой итерации цикла уменьшает значение счетчика в регистре СХ на 1. Заметьте, что при такой организации цикла все операции по его организации выполняются «вручную».Но, учитывая важность такого алгоритмического элемента, как цикл, разработчики процессора ввели в систему команд группу из трех команд, облегчающую программирование циклов.
Эти команды также используют регистр ЕСХ/СХ как счетчик цикла. Дадим краткую характеристику этим командам.Команда LOOP позволяет организовать циклы (loops), подобные циклам forв языках высокого уровня с автоматическим уменьшением счетчика цикла. Синтаксис команды:loop метка_переходаКоманда реализует описанные далее действия.1. Декремент регистра ЕСХ/СХ.2. Сравнение регистра ЕСХ/СХ с нулем:П если (ЕСХ/СХ) > 0, то управление передается на метку перехода;П если (ЕСХ/СХ) = 0, то управление передается на следующую после LOOP команду.Команды LOOPE и LOOPZ (Loop still сх <> 0 or Zero flag = 0 — повторить цикл покаСХ <> 0 или ZF = 0) — абсолютные синонимы, поэтому используйте ту команду, которая вам больше нравится. Синтаксис команд:loope/loopz метка_переходаКоманды реализуют описанные далее действия.1.
Декремент регистра ЕСХ/СХ.2. Сравнение регистра ЕСХ/СХ с нулем и анализ состояния флага нуля ZF:П если (ЕСХ/СХ) > 0 и ZF = 1, управление передается на метку перехода;Организация циклов231D если (ЕСХ/СХ) = 0 или ZF=0, управление передается на следующую после ШОРкоманду.Команды LOOPNE и LOOPNZ (Loop still ex <> 0 or NonZero flag = 0 — повторитьцикл, пока СХ <> 0 или ZF = 1) также абсолютные синонимы. Синтаксис команд:loopne/loopnz метка_переходаКоманды реализуют описанные далее действия.1. Декремент регистра ЕСХ/СХ.2.
Сравнение регистра ЕСХ/СХ с нулем и анализ состояния флага нуля ZF:П если (ЕСХ/СХ) > 0 и ZF = 0, управление передается на метку перехода;П если (ЕСХ/СХ) = 0 или ZF = 1, управление передается на следующую после LOOPкоманду.Команды LOOPE/LOOPZ и LOOPNE/LOOPNZ по принципу своей работы являютсявзаимнообратными. Они расширяют действие команды LOOP тем, что дополнительно анализируют флаг ZF. Это дает возможность организовать досрочный выход изцикла, используя этот флаг в качестве индикатора. Типичное применение этихкоманд связано с операцией поиска определенного значения в последовательности или со сравнением двух чисел.Недостаток команд организации цикла LOOP, LOOPE/LOOPZ и LOOPNE/LOOPNZ заключается в том, что они реализуют только короткие переходы (от -128 до+127 байт). Для работы с длинными циклами придется использовать командыусловного перехода и команду JMP (см.
листинг 10.2), поэтому постарайтесь освоить оба способа организации циклов. Рассмотрим несколько примеров организации циклов с помощью команд LOOP, LOOPE/LOOPZ и LOOPNE/LOOPNZ.Программа из листинга 10.2 с использованием команды организации циклабудет выглядеть так, как показано в листинге 10.3.Листинг 10.3. Подсчет нулевых байтов с использованием командуправления циклом<1> ;prg_10_3.asm<2> model small<3> .stack 100h<4> .data<5> len equ 10количество элементов в mas<6> mas db 1,0.9,8.0.7,8,0,2,0<7> .code<8> start:<9>mov ax,@data<10>mov ds.ax<11>mov ex,len;длину поля mas в сх<12>xor ax,ax<13>xor si,si<14>jcxz exit;проверка сх на 0, если 0, то выход<15>cycl:<1б>cmp mas[si],0;сравнить очередной элемент mas с 0<17>jne ml;если не равно 0, то на ml<18>inc al;в al - счетчик нулевых элементов<19> ml:<20>inc si;перейти к следующему элементу<21>loop cycl<22>exit:продолжение ?У232Глава 10.
Команды передачи управленияЛистинг 10.3 (продолжение)<23>mov ax,4c00h<24>i n t 21h;возврат управления операционной системе<25>end startЗаметьте, что у команды JCXZ в строке 14 осталась только одна функция — недопустить выполнения «пустого» цикла, поэтому несколько изменилось ее местов тексте программы: теперь она стоит перед меткой начала цикла cycl. Изменениеи контроль содержимого регистра СХ в процессе выполнения каждой итерации выполняет команда ШОР (строка 21).Рассмотрим пример, в котором продемонстрируем типичный подход к использованию команды LOOPNZ.
В программе из листинга 10.4 ищется первый нулевойэлемент в поле mas. Интерес представляют строки 20 и 21. Команда LOOPNZ на основании содержимого регистра СХ и флага ZF принимает решение о продолжениицикла. Выход из цикла происходит в одном из двух случаев: СХ = 0 (просмотренывсе элементы поля mas) или ZF = 1 (командой СМР обнаружен нулевой элемент).Назначение следующей команды JZ (строка 21) в том, чтобы распознать конкретную причину выхода из цикла. Если выход из цикла произошел после просмотрастроки, в которой нет нулевых элементов, то флаг JZ не сработает и будет выданосообщение об отсутствии нулевых элементов в строке (строки 7, 23-25).
Если выход из цикла произошел в результате обнаружения нулевого элемента, то в регистре SI окажется номер позиции этого элемента в поле mas и при необходимостиможно продолжить обработку. В нашем случае мы просто завершаем программу —переходим на метку exit.Листинг 10.4. Пример использования команды loopnz<1> ;prg_10_4.asm<2> model small<3> .stack 100h<4> .data<5> len equ 10 ;количество элементов в mas<6> mas db 1,0,9,8,0,7,8,0,2,0<7> message db "В поле mas нет элементов, равных нулю,$"<8> .code<9> start:<10>mov ax,@data<11>mov ds.ax<12>mov ex,len;длину поля mas в сх<13>xor ax,ax<14>xor si,si<15>jcxz exit;проверка сх на О, если 0, то выход<1б>mov si,-l;готовим si к адресации элементов поля mas<17>cycl:<18>inc si<19>cmp mas[si],0;сравнить очередной элемент mas с 0<20>loopnz cycl<21>jz exit;выяснение причины выхода из цикла<22>;вывод сообщения, если нет нулевых элементов в mas<23>mov ah,9<24>mov dx,offset message<25>int 21h<26>exit:<27>mov ax,4c00h<28>int 21h;возврат управления операционной системе<29>end startОрганизация циклов233Читатели, имеющие даже небольшой опыт программирования на языках высокого уровня, знают, что очень часто возникает необходимость во вложенных циклах.
Самый простой пример — обработка двухмерного массива. Работу с массивами, в том числе двухмерными, мы рассмотрим в главе 13, пока же разберемсяс основными принципами организации вложенных циклов. Основная проблема,которая при этом возникает, — как сохранить значения счетчиков в регистре ЕСХ/СХ для каждого из циклов. Для временного сохранения счетчика внешнего циклана время выполнения внутреннего доступно несколько способов: задействоватьрегистры, ячейки памяти или стек. В следующем фрагменте программы имеетсятри цикла, вложенные один в другой.
Этот фрагмент можно рассматривать какшаблон для построения других программ с вложенными циклами.<2>mov сх,100<3> cycl_l:<4>push схколичество повторений цикла cycl_l;счетчик цикла cycl_l в стек<5>; . . . команды цикла cycl_l<6>mov с х , 5 0количество повторений цикла cycl_2<7> c y c l _ 2 :<8><9><10><11><12><13><14><15><1б><17><18><19><20>push сх;счетчик цикла cycl_2 в стек;...;команды цикла cycl_2mov с х , 2 5количество повторений цикла cycl_3cycl_3:; .
. . к о м а н д ы цикла cycl_3loop cycl_3;...команды цикла cycl_2pop схвосстановить счетчик цикла cycl_2loop c y c l _ 2; . . . к о м а н д ы цикла cycl_lpop схвосстановить счетчик цикла cycl_lloop cycl_l;...В качестве примера рассмотрим фрагмент программы, которая обрабатываетспециальным образом некоторую область памяти (листинг 10.5).
Область памятирассматривается как совокупность пяти полей, содержащих 10 однобайтовых элементов. Требуется заменить все нулевые байты в этой области значением Offh.Листинг 10.5. Пример использования вложенных циклов<1> ;prg_10_5.asm< 2 > model small<3> .stack 100h<4> .data<5> mas db 1,0,9,8,0,7,8 ,0,2 ,0db 1,0,9,8,0,7,8 ,0,2 ,0db 1,0,9,8,0 7 8 PI ? 0db 1 0,9,8,0 7 R P) ? 0db 1,0,9,8,0,7,8,0,2 ,0.
codestart:mov ax,@datamov ds.axxor ax, axlea bx.masmov ex, 5cycl_l:push exxor si , siпродолжение234Глава 10. Команды передачи управленияЛистинг 10.5(продолжение)mov ex, 10<20>cycl_2:<21>стр byte ptr [bx+si] ,0<22><23>jne no zeromov byte ptr [bx+si] ,0ffh<24><25>no_zero:<26>inc siloop cycl_2<27>pop ex<28>add bx,10<29><30>loop cycl_l<31>exit:mov ax,4c00h<32>int 21h;возврат управления операционной системе<33><34>end startОграничение области видимости для метокПрименение команд, описанных в данной главе, предполагает довольно интенсивное использование меток.
На определенном этапе работы многие программистытиповые фрагменты кода берут из ранее разработанных программ, реализуя своеобразное фрагментарно-модульное программирование. При этом может оказаться, что фрагменты кода имеют одинаковые метки. Что делать — пересматриватьвесь текст? Если не проанализировать код с должным вниманием, потом можнопровести много часов за работой с отладчиком или, что еще хуже, программа начнет неправильно работать у заказчика.