Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
74
Добавлен:
11.02.2014
Размер:
272.07 Кб
Скачать

Министерство образования и науки Российской Федерации

Государственное образовательное учреждение высшего профессионального образования

Оренбургский государственный университет

Кафедра систем автоматизации производства

Курс: «Операционные системы»

Лаборатораная работа №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