
лабораторная работа / лабораторные работы по ASSAMBLER / upravlyayushie_struktury_i_procedury_v
.pdfПрограммирование типовых управляющих структур
Условный оператор if-else
Условный оператор if-else используется для принятия решения о дальнейшем пути исполнения программы. Синтаксис условного оператора в нотации языка Pascal:
if выражение then оператор1;
else
оператор2
Алгоритм работы условного оператора – вычисляется логическое значение выражения: если оно истинно, то выполняется оператор1, в противном случае – оператор2.
На ассемблере данные варианты условного оператора можно реализовать следующим образом:
; полный вариант оператора if выражение then оператор1 else оператор2
cmp op1,op2 |
; вычисление выражения |
jne else1 |
|
; … |
; последовательность команд, соответствующая оператор1 |
jmp endif |
|
else1: |
|
;… |
; последовательность команд, соответствующая оператор2 |
endif: |
; конец полного условного оператора |
; … |
|
Вместо команды СМР можно использовать любую команду, изменяющую флаг, который будет анализироваться последующим оператором условного перехода. Аналогично и с командой JNE, вместо которой может стоять требуемая в данном вычислительном контексте команда условного перехода.
Оператор выбора case
Оператор case (переключатель) в программе на ассемблере можно реализовать несколькими способами: использованием команд сравнения и с использованием таблицы. В нотации языка Pascal синтаксис оператора case выглядит так:
case константное_значение_«выражение» of константное выражение_1: операнд1; константное выражение_2: операнд2;
…
константное выражение_n: операндN
else
операнд_default;
end;
Первый способ реализации заключается в организации последовательных сравнений с условными переходами. К примеру, необходимо обработать три возможные альтернативы в программе, которые идентифицируются целочисленными значениями
1,2,3 («выражение»):
; … |
; формирование константное_значение_«выражение |
11
mov al,константное_значение_«выражение»
cmp al,1 |
; проверка первой альтернативы (константное выражение_1=1?) |
jе handle_condition1 ; равно, идем на обработку |
|
cmp al,2 |
; проверка второй альтернативы (константное выражение_2=2?) |
je handle_condition2 ; равно, идем на обработку |
|
cmp al,3 |
; проверка третьей альтернативы (константное выражение_3=3?) |
je handle_condition2 ; равно, идем на обработку
; если condition <> 1,2,3 , то производим обработку по умолчанию
;… |
; последовательность команд для обработки по умолчанию |
jmp end_switch |
; уходим на конец switch |
handle_conditionl: |
|
; … |
; последовательность команд для обработки handle_condition1 |
jmp end_switch |
; уходим на конец switch |
handle_condition2: |
|
; … |
; последовательность команд для обработки handle_condition2 |
jmp end_switch |
; уходим на конец switch |
handle_condition3: |
|
; … |
; последовательность команд для обработки handle_condition3 |
end_switch: |
|
;… |
; продолжение программы |
Второй (табличный) способ. Для реализации рассматриваемого способа в памяти моделируется некоторое подобие таблицы. Каждая строка таблицы состоит из двух ячеек. Строки таблицы располагаются в памяти последовательно – друг за другом. В первой ячейке таблицы располагается значение константное_выражение_n, во второй ячейке – адрес перехода, если выполняется условие константное_значение_«выражение» = константное_выражение_n. Целью адреса перехода может быть процедура или метка, соответствующая фрагменту кода, обрабатывающему выполнение условия, заданного в заголовке оператора выбора. Реализация табличным способом будет выглядеть так:
.data
table_switch |
db 1 |
|
dw handle_conditionl |
|
db 2 |
|
dw handle_condition2 |
|
db 3 |
|
dw handle conditions |
;…
.code
;… формирование константное_значение_«выражение» mov al,константное_значение_«выражение»
mov bx,offset table_switch
mov cx,3 |
; счетчик циклов = количество альтернатив |
next_condition: |
|
cmp al,[bx] |
; проверка очередной альтернативы |
jne next |
; к следующему элементу |
jmp word ptr [bx+1] |
; на обработку совпадения |
next: |
|
add bx,3 |
; адрес следующей строки таблицы > bx |
loop next_condition |
|
;default:
;если condition<>1,2,3, то производим обработку по умолчанию
12
; … |
; последовательность команд для обработки по умолчанию |
jmp … |
; уходим, куда нужно |
handle_condition1: |
|
; … |
; последовательность команд для обработки handle_condition1 |
jmp … |
; уходим, куда нужно |
handle_condition2: |
|
; … |
; последовательность команд для обработки handle_condition2 |
Jmp … |
; уходим, куда нужно |
handle_condition3: |
|
; … |
; последовательность команд для обработки handle_condition3 |
jmp … |
; уходим, куда нужно |
; … |
; продолжение программы |
Оператор цикла с предусловием while
Оператор цикла с предусловием while имеет следующий формат: while выражение условие do
тело цикла
На ассемблере это может выглядеть так:
while_begin: |
|
cmp al,1 |
; вычисление логического значения «выражение условие» |
jne end_while |
; ЕСЛИ не равно ТО ПЕРЕЙТИ НА end_while |
; … |
; что то делаем – тело цикла |
jmp while_begin |
; переход на начало очередной итерации цикла |
end_while: |
; конец цикла |
; … |
; продолжение программы |
Операторы continue и break
Прекращение выполнения цикла возможно в двух случаях: значение выражениеусловие равно FALSE или имеет место безусловная передача управления за пределы.
Алгоритм выполнения операторов break, goto и continue прост, они передают управление в определенную точку программы:
–break: сразу за конец цикла;
–goto: в произвольное место программы;
–continue: на начало последнего открытого оператора while, do или for.
В программе на ассемблере эти операторы реализовываются с помощью команды безусловного перехода JMP, которая передаст управление в нужную точку программы.
Оператор цикла с постусловием do-while
Его формат: repeat
тело цикла
until (выражение условие)
Псевдокод на ассемблере реализации этого оператора выглядит так:
do_while_begin: |
|
; … |
; операторы цикла |
13
; вычисление логического значения «выражение условие» ЕСЛИ «выражение условие» = FALSE ТО ПЕРЕЙТИ НА end_while
ПЕРЕЙТИ на do_while_begin: ; переход на начало очередной итерации цикла
end_while: |
; |
конец цикла |
;… |
; |
продолжение программы |
Оператор итерационного цикла for
Формат:
for инициализация_счетчика to выражение do тело цикла
Ассемблер с помощью команды LOOP поддерживает только один вариант организации такого цикла. Реализацию произвольного варианта цикла for можно с помощью следующего псевдокода:
;инициализация переменной цикла for_begin:
;вычисление логического значения «выражение условие» ЕСЛИ «выражение условие» = FALSE ТО ПЕРЕЙТИ НА end_for
; … |
; операторы |
цикла |
|
; … |
; вычисляем |
выражение – очередное значение переменной цикла |
|
ПЕРЕЙТИ на for_begin: |
; переход на начало очередной итерации цикла |
||
end_for: |
|
; конец цикла |
|
; … |
|
; продолжение программы |
В качестве примера рассмотрим программу, суммирующую или вычесляющую разность в зависимости от выбора пользователя и выводящую результат на экран в виде строкового представления (листинг 6).
Листинг 6 – Комплексный пример
.model small |
|
|
.stack 100h |
|
|
.data |
|
|
A dw 7934 |
; 1EFEh |
|
B dw 2471 |
; 9A7h |
|
tbl db 31h |
; условие перехода |
|
dw sum |
; адрес метки для перехода |
|
db 32h |
|
dw subt
szSelect db 'a = 7934',10,13,'b = 2471',10,13,'1 operation "+"; 2 operation " ": ','$'
szResult db 10,13,'Result = ' |
|
|
Result |
db '00000','$' |
; символьная строка для результата |
.code |
|
|
mov ax,@data |
|
|
mov ds,ax |
|
|
mov es,ax |
|
|
mov ah,9 |
|
|
lea dx,szSelect |
|
|
int 21h |
; вывод приглашения |
|
mov ah,1 |
; функция ввода |
|
int 21h |
|
|
14
mov bx, offset tbl |
; загрузка таблицы переключателей |
|
mov cx,2 |
|
; число альтернатив |
next_condition: |
|
|
cmp al,[bx] |
; проверка аьтернативы |
|
jne next |
|
; альтернатива не подходит |
jmp word ptr [bx+1] |
; переход на метку с адресом обработчика |
|
next: |
|
|
add bx,3 |
|
; адрес следующей строки (альтернатива) |
loop next_condition |
|
|
sum: |
; переход если выбран пункт "+" (сумма) |
|
mov ax,A |
; ax = 7934 |
|
add ax,B |
; ax = 7934 + 2471 = 10405d = 28A5h |
|
jmp exit_switch |
|
|
subt: |
; переход если выбран пункт " " (разность) |
|
mov ax,A |
; ax = 7934 |
|
sub ax,B |
; ax = 7934 2471 = 5463d = 1557h |
|
exit_switch: |
; выход из переключателя |
lea si,Result+4 ; адрес конца строки результата
call IntStr ; функция перевода числа из 2 ного представления в строку
|
; параметры: ax число, si адрес строки |
mov ah,9 |
; вывод результата в виде строки |
lea dx,szResult int 21h
mov ah,1 int 21h
mov ax, 4C00h int 21h
IntStr proc mov cx,10
next_digit:
cmp ax,0010 jb exit xor dx,dx div cx
or dl,30h mov [si],dl dec si
jmp next_digit
exit:
or al,30h mov [si],al
ret
IntStr endp end
15
Задания
1 X DB 206
Определить, будет ли сделан переход на метку MET при выполнении следующих команд:
а) cmp x,210 |
б) cmp x,210 |
в) cmp x, 40 |
г) cmp x, 40 |
д) cmp x,216 |
ja met |
je lab |
jg met |
jl met |
jl met |
2 X DW ? ; число со знаком
Определить, какой из следующих фрагментов правильно реализует оператор if X>80 then
X:=X 1
else
X:=X+1
а) cmp x,80 |
б) cmp x,80 |
в) cmp |
x,80 |
г) cmp |
x,80 |
jle m |
jg m |
jle |
m |
jng |
m |
dec x |
dec x |
dec |
x |
dec |
x |
m: inc x |
jmp l |
jmp |
l |
jmp |
l |
|
m: inc x |
m: inc x |
m: inc x |
||
|
l: |
l: |
|
l: |
|
3 Пусть A, B и C – знаковые переменные-слова. Записать в регистр DL значение 3, 2, 1 или 0 в зависимости от того, может ли существовать треугольник с такими длинами сторон (и если да, то какого он вида – равносторонний (3), равнобедренный (2) или какой-то иной (1)) или не может (0). Условие существования треугольника: сумма длин двух сторон должна быть больше третей стороны.
4 N DB ? ; N≥1
F DW ?
Записать в F:
а) N-е число Фибоначчи (FN);
б) первое из чисел Фибоначчи, превосходящих 10000. (Определение чисел Фибоначчи Fk: F0=F1=1, Fk=Fk-1+Fk-2.)
5 Напечатать таблицу умножения (в десятичной системе счисления) для числа N (номер по журналу). Пример для числа 9:
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
9 |
9 |
18 |
27 |
36 |
45 |
54 |
63 |
72 |
81 |
16