Лаб8. Циклы. Процедуры
Цель работы: изучение операторов цикла, приобретение навыков использования команд циклов при написании ассемблерных программ; организация и вызов процедур, передача параметров в процедуры и возврат результатов из процедур.
Теоретическая часть
Команды циклов
Циклы организуются для многократного повторения одной или нескольких команд программы или процедуры. Цикл можно организовать, используя команды условного и безусловного переходов, рассмотренных в лабораторной работе 6, а можно с помощью специальных команд. Формат команд представлен в таблице.
ТАБЛИЦА ФОРМАТОВ КОМАНД ЦИКЛА
Название команды | Мнемоника и формат команды | Проверяемое условие цикла |
Повторять цикл | LOOP label | (ECX/ CX) = 0 |
Повторять цикл, пока ноль или равно | LOOPZ/ LOOPE label | (ECX/ CX) = 0 или ZF = 0 |
Повторять цикл, пока не ноль или не равно | LOOPNZ/ LOOPNE label | (ECX/ CX) = 0 или ZF = 1 |
Переход по CX | JCXZ label | (ECX/ CX) = 0 |
Команда LOOP и ее расширения позволяют организовывать циклы, подобные циклам в языках высокого уровня. Регистр ECX/CX служит счетчиком максимального числа повторений цикла, его загружают перед началом цикла. Все команды, за исключением команды JCXZ, которая не изменяет ECX/CX, вычитают единицу из ECX/CX перед повторением цикла. В случае, когда условие цикла удовлетворяется, управление передается на метку label, в противном случае управление переходит на следующую за LOOP команду. Флажки этими командами не модифицируются. Метка label должна находиться в диапазоне от -128 до 127 байтов от команды, следующей за командой цикла.
Примеры.
;складываем числа от 1 до 12 mov bx, 0 mov ax, 0 mov cx, 12 ;количество повторений цикла a1: inc bx add ax, bx ;складываем числа loop a1 ;повторять, пока cx не станет равен 0 ;тот же самый пример, но с использованием jcxz ;складываем числа от 1 до 12 mov bx, 0 mov ax, 0 mov cx, 12 ;количество повторений цикла a1:jcxz a2 ;выход из цикла, если cx равен 0 inc bx add ax, bx ;складываем числа dec cx jmp a1 ;переход на начало цикла a2: ... ;ищем первую букву ’а’ в строке, адресуемой регистром bx ;длина строки 120 байтов mov cx, 120 ;количество повторений цикла m1: inc bx cmp byte ptr[bx],’а’;ищем первую букву ’а’ loopne m1 ;повторяем цикл 120 раз или пока не найдем ’а’ ;проверяем, закончилась ли строка или найдена ’а’ jz naidena ... ;строка закончилась, буква ’а’ не найдена naidena:... ;адрес ’а’ в bx |
Обращение к процедурам
Процедура (подпрограмма) – это группа команд для решения конкретной подзадачи, получающая управление из точки вызова задачи более высокого уровня и возвращающая управление в эту точку.
Описание процедуры состоит из заголовка, тела и конца процедуры:
имя_процедуры PROC [расстояние] ;заголовок процедуры
;команды, директивы Ассемблера – тело процедуры
ret
имя_процедуры ENDP ;конец процедуры
Имя процедуры – это идентификатор (символический адрес), по которому происходит обращение к процедуре. Необязательный параметр расстояние характеризует возможность обращения к процедуре из другого сегмента кода. Этот параметр может принимать значения: NEAR – для процедур ближнего вызова (описание процедуры находится в том же самом сегменте кода, что и основная программа) и FAR – для процедур дальнего вызова (описание процедуры находится в другом сегменте кода). По умолчанию этот параметр равен NEAR.
Процедура может размещаться в любом месте программы, но так, чтобы на нее случайным образом не попало управление.
Процедуру можно разместить:
1) в начале программы (до первой исполняемой команды);
c_s segment assume cs:c_s pr1 proc near ... ret p1 endp begin: ;начало программы ... end begin |
2) в конце программы (после команды корректного завершения работы и возвращения управления операционной системе);
c_s segment assume cs:c_s begin: ... mov ah, 4ch int 21h ;корректное завершение работы ;и передача управления ОС ;ret ;можно использовать команду ret p1 proc near ... ret p1 endp c_s ends end begin |
3) внутри тела программы или другой процедуры (должен быть предусмотрен обход процедуры с помощью оператора jmp);
c_s segment assume cs:c_s begin: ... jmp m1 p1 proc near ... ret p1 endp m1: ... mov ah, 4ch int 21h ;корректное завершение работы ;и передача управления ОС c_s ends end begin |
4) в другом модуле.
Команда CALL осуществляет вызов процедуры, сохраняя предварительно в стеке адрес возврата – адрес команды, следующей после команды CALL. При выполнении команды CALL осуществляется передача управления по адресу с символическим именем имя_процедуры.
Формат команды CALL: CALL [модификатор] имя_процедуры
Модификатор может принимать значения NEAR или FAR, для обращения к процедурам ближнего или дальнего вызовов, соответственно.
Команда RET считывает из стека адрес возврата и загружает его в регистр IP/EIP или в пару регистров CS и IP/EIP, возвращая тем самым управление на команду, следующую в программе за командой CALL. Для процедур ближнего вызова адрес возврата полностью определяется содержимым регистра IP/EIP, а для процедур дальнего вызова – содержимым двух регистров: CS и IP/EIP. При этом команда CALL запоминает в стеке сначала значение регистра CS, а затем значение регистра IP/EIP.
Параметры в процедуру можно передавать через регистры, стек или через общую область памяти. Возвращать параметры можно аналогичным образом.
Примеры
;1. Фрагмент программы для вычисления в цикле выражения ;y = 5+6+7+8+9+10+16 mov cx, 6 ;количество циклов (10-5+1) mov ax, 0 ;накопитель результата mov bx, 5 ;первоначальное значение i=5 m: add ax, bx ;ax=5+6+… inc bx ;инкрементируем i loop m ;если цикл не завершен, возвращаемся на m add ax, 16 ;прибавляем к сумме 16 ;2. Программа и процедуры вывода сообщений dseg segment para public ’data’ m1 db ’message1’,10,13,’$’ m2 db ’message2’,10,13,’$’ contor1 dw 0 contor2 dw 1 dseg ends cseg segment para public ’code’ assume cs:cseg, ds:dseg main_pr proc ;основная программа ... lea dx, m1 ;параметр для процедуры print в dx call print lea dx, m2 ;параметр для процедуры print в dх call print ... mov ax,0 push ax ;параметр для incnum в стеке call incnum pop ax ;получение результата ... mov cx,offset contor1 push cx ;параметр для addnum в стеке call addnum mov cx,offset contor2 push cx ;параметр для addnum в стеке call addnum ret main_pr endp print proc near ;процедура вывода сообщений mov ah, 9 int 21h ret print endp incnum proc near ;процедура увеличения значения на 3 pop cx ;извлечение параметра из стека в сх add cx,3 push cx ret incnum endp ;процедура увеличения значения в памяти на 1 ;параметр передается через стек ;результат записывается в память в вызывающей программе addnum proc near pop bx ;извлечение адреса памяти из стека в bх mov ax,[bx] add ax,1 mov [bx],ax ;запись результата в память ret addnum endp cseg ends end main_pr end |
Задания
Написать программу на языке Ассемблер, которая использует процедуры для вычисления следующего выражения:
Оставить комментарий