Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
ЛЕКЦИЯ №4 Программирование разветвлений
Команда сравнения двоичных целых чисел.
Сmp dst, src - данная команда работает аналогично команде вычитания (sub), только приемник не меняется, но при этом устанавливается регистр флагов. Данная команда применяется для организации разветвлений и обычно используется с командами передачи управления.
Команды передачи управления
Команда безусловного перехода Jmp метка в Ассемблере. Jmp меняет содержимое регистра IP в случае: а) если метка имеет тип short и находится от места командировки на –128..127 б) если метка имеет тип near и находится от места командировки на -32768..32767 После трансляции код команды jmp может иметь длину 2 байта (short), 3 байта (near), пять байтов (far). Адрес перехода может быть задан в формате прямой адресации: Jmp M1 где М1 - label М1 – адрес этой метки определяется через пару СS: offsetM1 Команды условного перехода Условные переходы делятся на две группы: o Проверяющие результаты предыдущей арифметической или логической команды; o Управляющие итерациями фрагмента программы. Команды условного перехода выполняют или не выполняют передачу управления на указанный адрес в зависимости от состояния флагов процессора не момент выполнения команды. Эти команды проверяют различные комбинации флагов и условий. Если условие истинно, осуществляется передача управления на указанный адрес. Если условие неверно, управление передается команде, следующей за командой условного перехода. Все команды условного перехода являются короткими (SHORT), так что диапазон переходов в этих командах лежит в диапазоне от -128 до +127 байтов. Некоторые команды условного перехода проверяют текущее состояние регистра флагов, а затем в зависимости от кодов условия команда делает переход ( или не делает). Команды условного перехода не устанавливают флаги, а только проверяют их текущее состояние. Ранее рассмотренные арифметические и логические команды устанавливают флаги. Существуют четыре возможных соотношения между операндами без знака. Для того чтобы отличить команды условного перехода арифметики без знака от команд условного перехода арифметики со знаком используются мнемоники “выше” и “ниже”. В то время как мнемоники “больше” и “меньше” говорят о соотношении чисел со знаком, для арифметики без знака - мнемоники ”выше” ( above) и “ниже” ( below). Например, программа использует команду JA (переход, если выше). Микропроцессор выполняет условный переход в зависимости от соотношения двух чисел, считая их числами без знака, т.е. именно программист обязан выбрать правильную команду условного перехода. Отдельную группу команд условного перехода составляют арифметические сравнения со знаком. Существуют четыре условия, которые могут быть проверены: меньше ( JL), меньше или равно ( JLE), больше (JG), больше или равно ( JGE). Другие четыре мнемоники — отрицания этих четырех. В случае арифметики со знаком ассемблер использует мнемонику “меньше” ( less) и “ больше” (greater). Арифметические сравнения можно понять, используя их вместе с командой СМР. Например, CМР АХ, ВХ JL LABEL Переход произойдет, если содержимое регистра АХ меньше содержимого регистра ВХ. Можно читать комбинацию команд сравнения и условного перехода вместе, как один оператор: операнд результата встречается первым, затем идет условный оператор, а за ним следует исходный операнд. Другой пример: CMP CX, WORD_IN_MEMORY JNLE LABEL можно прочитать так: переход, если содержимое регистра СХ не меньше или равно содержимому ячейки памяти WORD_IN_MEMORY. Этот прием можно использовать для определения значения любой команды арифметического перехода, учитывающей знак или не учитывающий. Пример 1. ; Пример lab2: ; y=min(a*b, d*d) a_data segment para a dw 6 b dw 5 d dw 7 y dw? a_data ends a_stack segment para stack db 100 dup(0) a_stack ends a_code segment para assume ss: a_stack, ds: a_data, cs: a_code begin: mov ax, a_data mov ds, ax ; a*b-> BX mov ax, a imul b mov bx, ax ; d*d -> ax mov ax, d imul ax ; Развилка cmp bx, ax; d*d-a*b jle m1; if d*d< =a*b then jump label m1 ; else mov y, ax jmp finish m1: mov y, bx finish: mov ah, 4CH int 21h a_code ends end begin
Управление циклом Существует несколько команд условного перехода, предназначенных для управления циклами в программах. Команды цикла LOOP используют регистр СХ в качестве счетчика цикла. Команда LOOP уменьшает регистр СХ и передает управление на метку, если содержимое регистра СХ не равно 0. Если вычитание 1 из регистра СХ привело к нулевому результату, команда LOOP не делает перехода и выполняется следующая команда. Ниже приведен принцип работы команды LOOP: Программный фрагмент, который демонстрирует обычное использование команды LOOP: MOV CX, LOOP_COUNT BEGIN_LOOP: ; ... тело цикла LOOP BEGIN_LOOP
Программа помещает число итераций цикла в регистр СХ перед выполнением цикла. Затем выполняется тело цикла, а следом за ним — команда LOOP. Она уменьшает счетчик на 1, что соответствует единственной, только что выполненной итерации цикла. Если теперь счетчик в регистре СХ равен 0, программа продолжает выполнять команды после LOOP. Если счетчик не равен 0, управление возвращается к началу цикла, чтобы совершить еще один проход по телу цикла. Тело цикла выполняется столько раз, сколько было сначала задано содержимым регистра СХ. Замечание: Если программа внутри цикла изменяет регистр СХ, число итераций не будет соответствовать начальному значению в регистре СХ. Если СХ не был инициализирован или в него не была занесена величина 0, то команда loop вызовет повторение цикла 65536 раз. Существует специальная команда, позволяющая проверить содержимое счетчика СХ на 0 и передавать управление в точку, где обрабатывается эта ситуация: jcxz label_ ERROR Эту команду целесообразно использовать перед циклом, когда содержимое регистра СХ формируется программным путем, Эта команда проверяет текущее содержимое регистра СХ и делает переход, если оно равно 0. Команда не проверяет ни одного флага и не влияет ни на один из них. В следующем примере регистр СХ загружается из ячейки памяти, содержимое которой вычисляется во время выполнения программы. Может оказаться, что счетчик циклов нулевой, поэтому в примере используется команда JCХZ, чтобы проверить, нужно ли полностью пропустить тело цикла:
MOV CX, LOOP_COUNT_WORD JCXZ END_OF_LOOP BEGIN_LOOP: ; ... тело цикла LOOP BEGIN_LOOP END_OF_LOOP
Оставшиеся две команды цикла предоставляют еще больше возможностей при управлении циклами. Если команда LOOP выходит из цикла только когда в регистре СХ оказывается 0, то команда LOOPE ( цикл, пока равно) выходит из цикла, если установлен флаг нуля или если в регистре СХ получился 0. Тем самым становится возможным двойственное завершение цикла. Программа может загрузить в регистр СХ максимальное число итераций цикла, а затем проверять флаг нуля в конце каждого цикла на условие завершения. Команда LOOPNE (цикл, пока не равно) выполняет обратную проверку флага нуля: цикл здесь завершается, если регистр СХ достиг 0 или если установлен флаг нуля.
Популярное:
|
Последнее изменение этой страницы: 2016-04-11; Просмотров: 665; Нарушение авторского права страницы