
лабораторная работа / лабораторные работы по ASSAMBLER / upravlyayushie_struktury_i_procedury_v
.pdfМинистерство образования и науки Российской Федерации
Государственное образовательное учреждение высшего профессионального образования
Оренбургский государственный университет
Кафедра систем автоматизации производства
Курс: «Операционные системы»
Лаборатораная работа №2
Управляющие структуры и процедуры в языке программирования Ассемблер
Методические указания к лаборатоным и самостоятельным работам
Цель работы
Изучение команд передачи управления; знакомство с процедурами языка Ассемблер; программирование типовых управляющих структур: операторов выбора, циклов.
Общие сведения
Последовательно работают очень мало программ. Обычно в программе есть точки, в которых нужно принять решение о том, какая команда будет выполняться следующей. Это решение может быть:
–безусловным: в данной точке необходимо передать управление неследующей команде, а другой, которая находится на некотором удалении от текущей;
–условным: решение о том, какая команда будет выполняться следующей, принимается на основе анализа некоторых условий или данных.
По принципу действия команды процессора, обеспечивающие организацию переходов в программе, можно разделить на три группы.
–команды безусловной передачи управления:
–команды условной передачи управления:
–команды управления циклом:
Место, куда необходимо передать управление обозначается меткой. Метка – это символическое имя, обозначающее определенную ячейку памяти и предназначенное для использования в качестве операнда в командах передачи управления.
Метку можно определить двумя способами:
–оператором : (двоеточие);
–директивой LABEL.
Определение меток с помощью директива LABEL:
Символическое_имя label Тип
Следующие описания меток ближнего типа эквивалентны: ml:
mov ax,pole_l
ml label near
mov ax,pole_l
Команда безусловного перехода
Синтаксис команды безусловного перехода без сохранения информации о точке возврата:
jmp [модификатор] адрес_перехода
Здесь адрес_перехода представляет метку или адрес области памяти, в которой находится указатель перехода. Пример использования команды безусловного перехода показан в листинге 1.
2

Листинг 1 – Использование команды безусловного перехода
.model small
.stack 100h
.data
a db 67 b db 43
szHello db 'Hello world$' szExit db 'Exit program$'
; code
.code
mov ax,@data mov ds,ax mov es,ax
mov al,a |
|
mov bl,b |
|
add ax,bx |
|
jmp exit |
; код ниже и до метки exit не будет исполнен |
sub ax,bx |
; и управление перейдет сразу на код после метки exit |
mov ah,9 |
|
lea dx,szHello |
|
int 21h |
|
exit: |
|
mov ah,9 |
|
lea dx,szExit |
|
int 21h |
|
mov ah,1 |
|
int 21h |
|
mov ax, 4C00h |
|
int 21h |
|
end |
|
Процедуры
Для описания последовательности команд в виде процедуры в языке ассемблера используются две директивы: PROC и ENDP.
Синтаксис описания процедуры таков (рисунок 1).
Рисунок 1 – Синтаксис описания процедуры в программе
3
В заголовке процедуры (директиве PROC) обязательным является только задание имени процедуры.
Процедура может размещаться в любом месте программы, но так, чтобы на нее случайным образом не попало управление. Возможны следующие варианты размещения процедуры в программе:
– в начале программы (до первой исполняемой команды); model small
.stack 100h
.data
.code
my_proc proc near
;…
ret
my_proc endp start:
;…
end start
– в конце программы (после команды, возвращающей управление операционной системе);
model small
.stack 100h
.data
.code
start: ; …
mov ax,4c00h
int 21h ; возврат управления операционной системе my_proc proc near
; … ret
my_proc endp end start
– в другом модуле (библиотеке DLL).
В системе команд процессора есть две команды для работы с контекстом – CALL и
RET.
Команда CALL осуществляет вызов процедуры (подпрограммы). Синтаксис команды:
call [модификатор] имя_процедуры
Подобно команде JMP команда CALL передает управление по адресу с символическим именем имя_процедуры, но при этом в стеке сохраняется адрес возврата (то есть адрес команды, следующей после команды CALL) (рисунок 2).
Команда RET считывает адрес возврата из стека и загружает его в регистры CS и EIP/IP, тем самым возвращая управление на команду, следующую в программе за командой CALL Синтаксис команды:
ret [число]
4

Необязательный параметр [число] обозначает количество элементов, удаляемых из стека при возврате из процедуры.
Рисунок 2 – Содержимое стека до и после выполнения команды вызова процедуры
С директивой PROC используются еще несколько директив: ARG, RETURNS, LOCAL, USES. Директивы ARG и RETURNS назначают входным и выходным параметрам процедуры, передаваемым через стек, символические имена. Директива USES в качестве параметров содержит имена используемых в процедуре регистров. При обработке этой директивы ассемблер формирует входной и выходной коды процедуры (из команд PUSH и POP), обеспечивающие сохранение и восстановление регистров. Директива LOCAL предназначена для выделения кадра стека для локальных переменных, что позволяет экономить память, занимаемую программой в целом.
Пример использования процедур. В качестве параметра число в 16-ом виде, процедура возращает указатель на строковое представление переданного числа.
Листинг 2 – Применение процедур
.model small |
|
.stack 100h |
|
.data |
|
dig dw 9731 |
; 2603h |
hex db '0000$' |
|
.code |
|
mov ax,@data |
|
mov ds,ax |
|
mov es,ax |
|
lea si,dig |
; в si АДРЕС переменной |
lea di,hex |
; в di АДРЕС, куда копировать строку |
call HexToStr |
|
mov ah,9 |
|
lea dx,hex |
|
int 21h |
|
mov ah,1 |
|
int 21h |
|
mov ax, 4C00h |
|
int 21h |
|
5
HexToStr proc
.386
xor ax,ax
mov al,[si+1] ror ax,4
shr ah,4
or ax,0011000000110000b mov [di],ax
xor ax,ax mov al,[si] ror ax,4 shr ah,4
or ax,0011000000110000b mov [di+2],ax
ret
HexToStr endp end
Условные переходы
Процессор поддерживает 18 команд условного перехода, позволяющих проверить:
–отношение между операндами со знаком (больше или меньше);
–отношение между операндами без знака (выше или ниже);
–состояниями арифметических флагов ZF, SF, CF, OF, PF (но не AF). Команды условного перехода имеют одинаковый синтаксис:
jcc метка_перехода
Мнемокод всех команд начинается с символа «j». Вместо символов «сс» указывается конкретное условие, анализируемое командой. Возможные аббривиатуры приведены в таблице 1.
Таблица 1 – Значение аббревиатур в названии команды jcc
Мнемоническое |
Оригинальный |
Перевод |
Тип операндов |
обозначение |
термин |
|
|
e |
Equal |
Равно |
Любые |
n |
Not |
Нет |
Любые |
g |
Greater |
Больше |
Числа со знаком |
l |
Less |
Меньше |
Числа со знаком |
a |
Above |
Выше (в смысле больше) |
Числа без знака |
b |
Below |
Ниже (в смысле меньше) |
Числа без знака |
Для того чтобы принять решение о том, куда будет передано управление командой условного перехода, предварительно должно быть сформировано условие, на основании которого должно приниматься решение. Источниками такого условия могут быть:
–любая команда, изменяющая состояние арифметических флагов;
–команда СМР, сравнивающая значения двух операндов;
–состояние регистра ЕСХ/СХ.
6

Команда сравнения
Команда сравнения СМР (СоМРаге) имеет такой же, как у команды вычитания SUB принцип работы и выполняет вычитание операндов и по результатам сравнения устанавливает флаги, но не записывает результат вычитания на место первого операнда. Синтаксис команды СМР:
cmp операнд1, операнд2
Флаги, устанавливаемые командой СМР, можно анализировать специальными командами условного перехода. В таблице 2 представлен перечень команд условного перехода для команды СМР.
Таблица 2 – Перечень команд условного перехода для команды cmp
Типы |
Мнемокод команды |
Критерий условного перехода |
Значения флагов для |
|
операндов |
условного перехода |
|
|
перехода |
Любые |
JE |
операнд_1 = операнд_2 |
ZF=1 |
|
Любые |
JNE |
операнд_1 <> операнд_2 |
ZF = 0 |
|
Со знаком |
JL/JNGE |
операнд_1 < операнд_2 |
SF < > OF |
|
Со знаком |
JLE/JNG |
операнд_1 <= операнд_2 |
SF < > OF или ZF = 1 |
|
Со знаком |
JG/JNLE |
операнд_1 > операнд_2 |
SF = OF и ZF = 0 |
|
Со знаком |
JGE/JNL |
операнд_1 => операнд_2 |
SF = OF |
|
Без знака |
JB/JNAE |
операнд_1 |
< операнд_2 |
CF = 1 |
Без знака |
JBE/JNA |
операнд_1 |
<= операнд_2 |
СР = 1 или ZF = 1 |
Без знака |
JA/JNBE |
операнд_1 |
> операнд_2 |
CF = 0 и ZF = 0 |
Без знака |
JAE/JNB |
опсранд_1 |
=> операнд_2 |
CF = 0 |
Пример использования – фрагмент программы, который обнуляет поле pole_m длиной n байт:
.data
n equ 50
pole_m db n dup (?)
.code ; …
xor bx,bx ; bx=0
ml:
mov mem[bx],0 inc bx
cmp bx,n jne ml
exit: ; …
Так как команды условного перехода не изменяют флагов, то после одной команды СМР вполне могут следовать несколько команд условного перехода
7
Команды условного перехода и флаги
Мнемокоды команд, названия флагов и условия переходов приведены в таблице 3. Эти команды можно использовать после любых команд, изменяющих указанные флаги.
Таблица 3 – Команды условного перехода и флаги
Название флага |
Номер |
бита |
в |
Команда условного |
Значение флага для |
|
регистре eflags/flags |
перехода |
осуществления перехода |
||
Переноса CF |
1 |
|
|
JC |
CF = 1 |
Четности PF |
2 |
|
|
JP |
PF = 1 |
Нуля ZF |
6 |
|
|
JZ |
ZF = 1 |
Знака SF |
7 |
|
|
JS |
SF = 1 |
Переполнения OF |
11 |
|
|
JO |
OF = 1 |
Переноса CF |
1 |
|
|
JNC |
CF = 0 |
Четности PF |
2 |
|
|
JNP |
PF = 0 |
Нуля ZF |
6 |
|
|
JNZ |
ZF = 0 |
Знака SF |
7 |
|
|
JNS |
SF = 0 |
Переполнения OF |
11 |
|
|
JNO |
OF = 0 |
В листинге 3 приведен пример программы, производящей в строке символов длиной n байт замену строчных букв английского алфавита прописными. Представление строчных и прописных букв в таблице ASCII:
a – 0110 0001 … z – 0111 1010 А – 0100 0001 … Z – 0101 1010
Таким образом, для выполнения преобразования между строчными и прописными буквами достаточно всего лишь инвертировать 5-й бит.
Листинг 3 – Смена регистра символов
.model small
.stack 100h
.data
n equ 10 ; количество символов в строке str1 str1 db 'acvfgrndu',10,13,'$'
.code
mov ax,@data mov ds,ax mov es,ax
mov ah,9 lea dx,str1 int 21h
xor ax,ax |
|
lea bx,str1 |
; адрес строки в bx |
mov cx,n |
|
m1: |
|
mov al,[bx] |
; очередной символ из str1 в al |
cmp al,61h |
; убедиться, что код символа не меньше 61h |
8
jb next |
; если меньше, то не обрабатывать |
|
; и перейти к следующему символу |
cmp al,7ah |
; убедиться, что код символа не больше 7ah |
ja next |
; если больше, то не обрабатывать |
and al,11011111b |
; инвертировать 5 й бит |
mov [bx],al |
; символ – на его место в str1 |
next: |
|
inc bx |
; адресовать следующий символ |
dec cx |
; уменьшить значение счетчика в сх |
jnz m1 |
; если сх не 0, то переход на m1 |
mov ah,9 |
|
lea dx,str1 |
|
int 21h |
|
mov ah,1 |
|
int 21h |
|
mov ax, 4C00h |
|
int 21h |
; возврат управления операционной системе |
end |
|
Организация циклов
Организовать циклическое выполнение некоторого фрагмента программы можно, к примеру, используя команды условной передачи управления или команду безусловного перехода JMP. Пример – подсчет количества нулевых байтов в области mas (листинг 4).
Листинг 4 – Подсчет числа нулевых элементов
.model small
.stack 100h
.data
len equ 10 ; количество элементов в mas mas db 1,0,9,8,0,7,8,0,2,0
.code
mov ax,@data mov ds,ax mov es,ax
xor ax,ax |
|
xor si,si |
|
mov cx,len |
; длину поля mas в сх |
cycle: |
|
jcxz exit |
; проверка сх на 0, если 0, то выход |
cmp mas[si],0 |
; сравнить очередной элемент mas с 0 |
jne m1 |
; если не равно 0, то на ml |
inc al |
; в al – счетчик нулевых элементов |
m1: |
|
inc si |
; перейти к следующему элементу |
dec cx |
; уменьшить сх на 1 |
jmp cycle |
|
exit: |
|
mov ah,1 |
|
int 21h |
|
9
mov ax, 4C00h ; возврат управления операционной системе int 21h
end
Цикл организован тремя командами, JCXZ, DEC и JMP. Команда JCXZ выполняет здесь две функции: предотвращает выполнение «пустого» цикла (когда счетчик цикла в СХ равен нулю) и отслеживает окончание цикла после обработки всех элементов поля mas. Команда DEC после каждой итерации цикла уменьшает значение счетчика в регистре СХ на 1.
Команда LOOP позволяет организовать циклы (loops), подобные циклам for в языках высокого уровня с автоматическим уменьшением счетчика цикла. Синтаксис команды:
loop метка_перехода
Команда реализует описанные далее действия.
1.Декремент регистра ЕСХ/СХ.
2.Сравнение регистра ЕСХ/СХ с нулем:
–если (ЕСХ/СХ) > 0, то управление передается на метку перехода;
–если (ЕСХ/СХ) = 0, то управление передается на следующую после LOOP команду.
Программа из листинга 4 с использованием команды организации цикла будет выглядеть так, как показано в листинге 5.
Листинг 5 – Подсчет нулевых байтов с использованием команд управления циклом
.model small
.stack 100h
.data
len equ 10 ; количество элементов в mas mas db 1,0,9,8,0,7,7,8,0,2,0
.code
mov ax,@data mov ds,ax mov es,ax
xor ax,ax |
|
xor si,si |
|
mov cx,len |
; длину поля mas в сх |
cycle: |
|
cmp mas[si],0 |
; сравнить очередной элемент mas с 0 |
jne m1 |
; если не равно 0, то на ml |
inc al |
; счетчик нулевых элементов |
m1: |
|
inc si |
; перейти к следующему элементу |
loop cycle |
|
mov ah,1 |
|
int 21h |
|
mov ax, 4C00h |
|
int 21h |
; возврат управления операционной системе |
end |
|
10