Магда Юрий
Шрифт:
; и сохраняем его в регистре ЕВХ
lea ESI, label_array ; адрес массива меток -> ESI
mov [ESI], offset LI ; заполняем массив меток смещениями
mov [ESI+4], offset L2 ; меток LI, L2 и L3 mov [ESI+8], offset L3
lea EAX, err_exit ; сохраняем в регистре ЕАХ смещение
; метки для выхода из процедурь
; в случае ошибки
shl ЕВХ, 2 ; поскольку для адресации
; используются двойные слова,
; умножаем номер строки на 4
сmp ЕВХ, 8 ; значение учетверенного параметра
; не должно превышать 8 (номер строки
; лежит в диапазоне 0-2)
jle next1 ; верхнее значение меньше 8? Если
; да, следующая проверка
jmp EAX ; нет, параметр превышает значение 2,
; выйти из процедуры с ошибкой
next1 :
cmp EBX, 0 ; параметр не является отрицательным
; числом? Если
jge get_string ; нет, продолжить выполнение
; процедуры
jmp EAX ; да, параметр вне диапазона, выйти
; с ошибкой
get_string: ; параметр находится в нужном
; диапазоне, получить адрес
; соответствующей строки и выйти из
; процедуры
cmovge EAX, [ESI][EBX]
jmp EAX
L1: ; сюда передается управление при
; значении входного параметра,
; равном 0
lea EAX, s1 ; адрес строки s1 -> EAX
jmp exit ; выход из процедурь
L2: ; сюда передается управление при
; значении входного параметра,
; равном 1
lea EAX, s2 ; адрес строки s2 -> EAX
jmp exit ; выход из процедурь
L3: ; сюда передается управление при
; значении входного параметра,
; равном 2
lea EAX, s3 ; адрес строки s3 -> EAX
jmp exit ; выход из процедурь
err_exit: ; сюда передается управление
; при возникновении ошибки
lea EAX, err ; адрес сообщения об ошибке -> ЕАХ
exit:
pop EBP
ret
_case_l endp
end
Анализ работы процедуры начнем со строк
lea ESI, label_array
mov [ESI], offset L1
mov [ESI+4], offset L2
mov [ESI+8], offset L3
Как и в предыдущем примере, вначале заполняем массив меток смещениями используемых ветвей программы. Поскольку 32-разрядные приложения работают со смещениями, равными двойному слову, то наш массив labelarray состоит из трех двойных слов, в которых и сохраняются смещения меток LI, L2 и L3. Все эти действия и выполняют четыре команды, показанные выше.
Следующая команда помещает в регистр ЕАХ смещение метки, куда должно передаваться управление в случае ошибки:
lea EAX, err_exit
Для передачи управления в нашей процедуре используется команда
jmp EAX
Она принимает в качестве операнда регистр (в данном случае – ЕАХ), содержащий смещение команды, куда передается управление.
С помощью следующей команды устанавливается смещение одной из меток (LI, L2 или L3), в которую должно передаваться управление при корректном значении параметра процедуры:
sh1 EBX, 2
Фрагмент программного кода, в котором выполняется проверка параметра на принадлежность диапазону 0-2, думаю, понятен и в объяснениях не нуждается. Если полученный параметр корректен, то выполняется команда
cmovge EAX, [ESI][EBX]
Остановимся на работе этой инструкции ассемблера более подробно. Описание группы команд, к которой принадлежит cmovge, приводится далее в этой главе, но в нашем случае эта инструкция выполняет две функции:
– анализирует результат предыдущей операции (флаг SF);
– если SF = 1, то в регистр ЕАХ помещается смещение одной из меток (LI, L2 или L3). Само смещение находится по адресу, равному сумме адресов массива label_агтау (регистр ESI) и индекса строки (регистр ЕВХ).
Подобную процедуру при желании можно усовершенствовать и использовать для организации ветвлений в программах на ассемблере.
5.3. Организация циклов
Очень часто условные переходы используются при программировании циклических операций, или циклов, когда обрабатывается группа элементов. Количество итераций (прохождений) в цикле чаще всего определяется количеством обрабатываемых элементов, хотя это и не обязательно. Цикл может закончиться в одном из двух случаев:
– выполнены все итерации;