assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 54
Текст из файла (страница 54)
.-.формирование константное_значение_"выражение"mov al,константное_значение_"выражение"mov bx,offset table_switchmov cx,3;счетчик циклов=количество альтернативnext_condition:cmp al,[bx]щроверка очередной альтернативыjne next_;к следующему элементуcall word ptr [bx+1];на обработку совпаденияjmp end_switchadd bx,3;адрес следующей строки таблицы -> bxnext_: loopnext_condition;default:;если condition<>!|2|3, то производим обработку по умолчанию240Глава 11. Программирование типовых управляющих структур;...end_switch:;...последовательность команд для обработки по умолчаниюпродолжение программыОператоры циклаВ предыдущей главе мы рассматривали общую концепцию реализации цикловв программах на языке ассемблера.
В данном разделе обсудим способы организации циклов, традиционно поддерживаемых большинством языков высокого уровня. Для полноты изложения нам, возможно, придется повторить некоторые тезисы предыдущей главы.Оператор цикла с предусловием whileОператор цикла с предусловием while имеет следующий формат:while (выражение-условие)тело циклаДля облегчения реализации этого оператора приведем его псевдокод, близкийк нотации ассемблера:while_begin:вычисление логического значения "выражение-условие"ЕСЛИ "выражение-условие"=РА1_5Е ТО ПЕРЕЙТИ НА end_whileоператоры циклаПЕРЕЙТИ на while_begin '.переход на начало очередной итерации циклаend_while:;конец цикла;...продолжение программыНа ассемблере это может выглядеть так:while_begin:cmp a I,1;вычисление логического значения "выражение-условие"jne end_while;ЕСЛИ не равно ТО ПЕРЕЙТИ НА end_while;что-то делаем - тело циклаjmp wriile_beginend_wrnle:;...;переход на начало очередной итерации цикла;конец циклапродолжение программыОператоры continue и breakПрекращение выполнения цикла возможно в двух случаях:и значение выражение-условие (см.
выше) равно FALSE;ж имеет место безусловная передача управления за пределы цикла (в программена языках С и C++ эти действия выполняют операторы break и goto).В языках С и C++ изменить последовательность выполнения тела цикла можно с помощью оператора continue.Алгоритм выполнения операторов break, goto и continue прост, они передаютуправление в определенную точку программы:break — сразу за конец цикла;goto — в произвольное место программы;continue — на начало последнего открытого оператора while, do или for.Операторы цикла241В программе на ассемблере естественнее всего реализовать эти операторы с помощью команды безусловного перехода JMP, которая передаст управление в нужную точку программы.Оператор цикла с постусловием do-whileПродолжим обсуждение операторов цикла различного типа.
Очередной — оператор цикла с постусловием do-while. Его формат в нотации языков С и C++:doтело циклаwhile (выражение-условие)Основная отличительная особенность данного оператора — в том, что операторы, составляющие тело цикла, выполняются хотя бы один раз. Близкий к нотацииассемблера псевдокод реализации этого оператора выглядит так:do_whi"le_begin:операторы циклавычисление логического значения "выражение-условие"ЕСЛИ_"выражение-условие"=РА15Е ТО ПЕРЕЙТИ НА end_whileПЕРЕЙТИ на do_while_begin: ;переход на начало очередной итерации циклаend_while:;конец цикла;...продолжение программыОператор итерационного цикла forОператор итерационного цикла for — это единственный оператор цикла, хотя бычастично поддерживаемый ассемблером на уровне команд.
Его формат в нотацииязыков С и C++:for (инициализация цикла; выражение-условие; выражение)тело циклаС точки зрения грамматики все три выражения в операторе for являются произвольными. Но обычно первое из них (инициализация цикла) предназначено дляприсвоения начального значения переменной цикла, второе (выражение-условие) вычисляет логическое значение для принятия решения о выходе из цикла, третье (выражение) вычисляет значение переменной цикла на очереднойего итерации.Ассемблер с помощью команды ШОР поддерживает только один вариант организации такого цикла, который был подробно рассмотрен в предыдущей главе. Дляреализации произвольного варианта цикла for может оказаться полезным следующий псевдокод:инициализация переменной циклаfor_begin:вычисление логического значения "выражение-условие"ЕСЛИ "выражение-условие"=РА15Е ТО ПЕРЕЙТИ НА end_forоператоры циклавычисляем выражение - очередное значение переменной циклаПЕРЕЙТИ на for_begin:;переход на начало очередной итерации циклаend_for:;конец цикла;...продолжение программыКакой цикл эффективнее? Тот, в котором меньше проверок и переходов.242Глава 11.
Программирование типовых управляющих структурОсобенности пакета MASMПакет MASM имеет встроенные средства, визуально приближающие написаннуюпрограмму к программам на языке высокого уровня. Это директивы для формирования конструкций, аналогичных условным и циклическим операторам языковвысокого уровня: .IF, .ELSE, .ELSEIF, .ENDIF, .REPEAT, .UNTIL, .WHILE, .ENDW, .BREAK,.CONTINUE. Всем директивам предшествует символ . (точка). Использование данных конструкций можно рекомендовать для повышения надежности кода.
Программист, оставаясь на уровне ассемблера, повышая логический уровень контролируемых им синтаксических конструкций, снижает вероятность ошибок логики,ускоряя тем самым весь процесс разработки.Условная конструкция .IFКонструкция .IF предназначена для генерации кода, функционально аналогичного условному оператору языков высокого уровня. Ее синтаксис:.IF условиепредложения блока IF[.ELSEIF] условиепредложения блока ELSEIF[.ELSE]предложения блока ELSE.ENDIFЗдесь слова .IF, .ELSEIF, .ELSE, .ENDIF — служебные, аусловие представляет одиниз следующих операторов:т оп! == оп2 — операнды равны;оп! != оп2 — операнды не равны;оп! > оп2 — больше;onl >= оп2 — больше или равно;onl < оп2 — меньше;onl <= оп2 — меньше или равно;onl & номер_бита — проверка бита;! onl — инверсия (NOT);onl && оп2 — логическое умножение (AND);onl || on2 — логическое сложение (OR);CARRY? - EFLAGS.CF=1?;OVERFLOW? - EFLAGS.OF=1?;PARITY? - EFLAGS.PF=1?;SIGN? - EFLAGS.SF=1?;ZERO? - EFLAGS.ZF=1?.Эти же условия используются в конструкциях .REPEAT, .WHILE, .BREAK, .CONTINUE(см.
далее). Сочетание операндов onl и оп2 должно быть допустимым для командассемблера, то есть выражение типа оЫ_1<оЫ_2 (память-память) ассемблер не пропустит.Особенности пакета MASM243Допускается вложение конструкций .IF. Назначение и использование директив .ELSE и .ELSEIF аналогичны соответствующим конструкциям в языках высокого уровня. Завершающая директива условного блока .ENDIF обязательна.Интерес для изучения представляет то, как ассемблер преобразует директивырассматриваемых нами конструкций высокого уровня в машинный код. Для этогонеобходимо вставить в любую программу, не имеющую синтаксических ошибок,фрагмент, подобный следующему:!if al==9mov.elseifmov.elsemov.endifах,1ax==0ax,2ax,3После этого необходимо выполнить компиляцию примера:M L .
E X E / F l / Z i Prg_6_l.asmКлюч /Fl предназначен для генерации файла листинга (по умолчанию не создается). Он намеренно вставлен в командную строку для того, чтобы не увидеть заменувысокоуровневых директив командами ассемблера в тексте листинга. Для визуализации замены встроенных макросов необходимо загрузить исполняемый модульв отладчик CodeView, выбрать в окне Source команду Options > Source Window и воткрывшемся окне Source Window Options выбрать режим отображения (Display Mode)Mixed Source and Assembly. Взору предстанет следующий смешанный код:2 5 : .
i f al==01792:000С 36803Е000100 CMP BYTE PTR 55:[0100].001792:0012 7505 JNZ 001926: mov ax,l1792:0014 B80100MOV AX,000127: .elseif ax==01792:0017 EB0C JMP 00251792:0019 0BC0 OR AX,AX1792:0016 7505 JNZ 002228: mov ax, 21792:0010 B80200MOV AX,000229: .else1792:0020 EB03 J M P 002530: mov ax , 31792:0022 B80300MOV AX,000331: .endifНа примере команд сравнения видно, как ассемблер выполняет оптимизациюкода. Для приведенного фрагмента программы ассемблер реализовал сравнениев двух вариантах:ж для переменной al==0 - CMP BYTE PTR SS:[0100],00;II для регистра ах==0 — OR AX,AX.Циклическая конструкция .REPEATКонструкция .REPEAT соответствует циклу с постусловием в языках высокогоуровня.Синтаксис конструкции:244Глава 11.
Программирование типовых управляющих структур.REPEATкоманды ассемблера.UNTIL условиеСуществует и второй тип конструкции .REPEAT:.REPEATкоманды ассемблера.UNTILCXZ [условие]Конструкция .REPEAT заставляет процессор повторно исполнять команды ассемблера пока условие истинно (не равно нулю). Особенностью такого цикла является то, что блок команд ассемблера выполняется хотя бы один раз. Исходя изконкретного условия, ассемблер при формировании его машинной реализациивыполняет необходимую оптимизацию. Что именно при этом происходит, можноувидеть, загрузив код в CodeView указанным ранее способом.Директива .UNTILCXZ может использоваться с проверкой дополнительногоусловия в виде выражение! == выражение2 или выражение! != выражение2, чтобыгенерировать команды ШОРЕ и LOOPNE. Директива .UNTILCXZ выполняет декрементрегистра ЕСХ и прекращает выполнение цикла при ЕСХ = 0.
При отсутствии условиядиректива .UNTILCXZ просто генерирует команду LOOP.Циклическая конструкция .WHILEКонструкция .WHILE соответствует циклу с предусловием в языках высокого уровня.Синтаксис конструкции:.WHILE условиекоманды ассемблера.ENDWДиректива .WHILE генерирует последовательность команд выполняющих блоккоманд ассемблера, если условие истинно. Директива .ENDW завершает блок команд ассемблера. Он заставляет вернуть управление конструкции .WHILE, котораяпосле проверки истинности условия либо заново инициирует выполнение блокакоманд ассемблера, либо передает управление команде, следующей за .ENDW. Конструкция .WHILE допускает вложенность, причем ассемблер выполняет необходимую оптимизацию для формирования наиболее эффективного кода.Конструкции .BREAK и .CONTINUEКонструкции .BREAK и .CONTINUE соответствуют аналогичным конструкциям языков высокого уровня.Директива .BREAK генерирует код выхода на первую команду, следующую зателом текущего цикла .WHILE или .REPEAT.