Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скляров И. Изучаем Assembler за 7 дней (2010).pdf
Скачиваний:
1335
Добавлен:
23.02.2015
Размер:
2.11 Mб
Скачать

http://www.sklyaroff.ru

59

3.5. Подпрограммы (процедуры)

В больших программах, чтобы избежать повторного написания группы из одних и тех же команд, их обычно оформляют в виде одной подпрограммы и вызывают по мере необходимости из любых мест программы.

Например, если часто нужно выводить на экран различные строки, то команды mov ah,9

int 21h

можно оформить в отдельную процедуру и вызывать ее тогда, когда требуется вывод на экран.

Подпрограммы оформляются с помощью двух директив: PROC (от англ. "procedure" — процедура) и ENDP (от англ. "end of procedure" — конец процедуры)

следующим образом:

имя_процедуры PROC параметр тело_процедуры

RET

имя_процедуры ENDP

В обеих директивах указывается одно и то же имя процедуры.

Директива PROC может иметь параметр — NEAR (от англ. близкий) или FAR (от англ. дальний). Если параметр отсутствует, то ассемблер будет считать, что он равен NEAR (в связи с этим параметр NEAR обычно не указывается). Соответственно процедура, оформленная с параметром NEAR (или с отсутствующим параметром) называется "близкой", а с параметром FAR — "дальней". К близкой процедуре нельзя обращаться из других сегментов команд, а к дальней — можно.

Вызов процедуры осуществляется с помощью команды CALL, которая имеет следующий синтаксис:

CALL имя_процедуры

А возврат из процедуры осуществляется с помощью команды RET.

В листинге 3.5 показана программа с применением процедуры. В процедуре (я дал ей имя Output) размещаются команды вызова функции DOS 9h. Процедура вызывается три раза для вывода на экран трех разных строк.

Листинг 3.5. Пример работы процедуры (proc.asm)

.model tiny

.code

org 100h

start:

mov

dx,offset message1

call

Output

mov

dx,offset message2

call

Output

mov

dx,offset message3

call

Output

ret

 

http://www.sklyaroff.ru

60

Output PROC

 

 

 

mov

ah,9

 

 

int

21h

 

 

ret

 

 

 

Output ENDP

 

 

 

message1

db

"Hello, Ivan!",0Dh,0Ah,'$'

message2

db

"Hello, Petr!",0Dh,0Ah,'$'

message3

db

"Hello, Fedor!",0Dh,0Ah,'$'

end start

3.6. Директива INCLUDE

Синтаксис директивы:

INCLUDE имя_файла

Директива INCLUDE вставляет в текущий исходный код программы исходный код из указанного файла. В языке программирования Си есть аналогичная директива

#include.

Заданное имя_файла должно указывать на существующий файл. Расширение включаемого файла не имеет значения, но содержимое включаемого файла должно иметь код на ассемблере. Ассемблер ищет файл в текущей директории. Если файл находится вне текущей директории, то необходимо указывать полный или частичный путь к файлу. Примеры:

INCLUDE file.asm

; Файл в текущей директории

INCLUDE local\as\entry.lib

; Частичное наименование пути

INCLUDE d:\include\define.inc

; Полный путь к файлу

Существует подобная директива:

INCLUDELIB имя_файла

Она указывает компоновщику имя дополнительной библиотеки или объектного файла, который потребуется при составлении данной программы. Мы эту директиву, равно как и директиву INCLUDE, будем часто использовать при изучении программирования под Windows.

Рассмотрим пример работы директивы INCLUDE. Создадим два файла: первый const.inc будет содержать несколько констант, а второй loop3.asm почти такой же, как в листинге 3.2, будет подключать с помощью INCLUDE файл const.inc и использовать из него константы (листинги 3.6 и 3.7).

Ассемблирование осуществляется как обычно выполнением командной строки: ml loop3.asm

при этом оба файла const.inc и loop3.asm должны находиться в одной директории.

Листинг 3.6. Содержимое включаемого файла const.inc

; содержимое файла const.inc cr EQU 0Dh

lf EQU 0Ah COUNT EQU 10

Листинг 3.7. Содержимое файла loop3.asm

.model tiny

http://www.sklyaroff.ru

 

61

INCLUDE const.inc

; включаем содержимое файла const.inc

.code

 

 

 

org

100h

 

 

start:

 

 

 

mov

cx,COUNT

; константа из файла const.inc

Mark:

 

 

 

mov

ah,9

 

 

mov

dx,offset message

int

21h

 

 

loop

Mark

 

 

ret

; используются константы cr и lf из файла const.inc message db "Hello, World!",cr,lf,'$'

end start

3.7. Конструкции времени исполнения программы

Выше мы рассмотрели, как организуются циклы и условные переходы с помощью команд ассемблера. Но в ассемблере еще предусмотрены специальные директивы, которые могут значительно упростить программирование на ассемблере, т. к. позволяют писать циклы и условные переходы в наглядном виде, почти также как на языках высокого уровня. Конструкции созданные с помощью этих директив преобразуются на этапе ассемблирования в команды микропроцессора.

Обратите внимание, что перед каждой такой директивой обязательно ставится точка (аналогичные директивы без точки выполняют другие действия, о чем мы узнаем ниже при рассмотрении директив условного ассемблирования).

Мы конструкции времени исполнения будем активно использовать в программах под ОС Windows (день 7).

Условные конструкции:

.IF условие

...

.ENDIF

Если условие "истина", то выполняются команды между .IF и .ENDIF. Директива .IF может также содержать .ELSE:

.IF условие

...

.ELSE

...

.ENDIF

В этом случае если условие "истина", то выполняются команды между .IF и .ELSE, в противном случае — от .ELSE до .ENDIF.

Директива .IF может также включать множество операторов .ELSEIF:

http://www.sklyaroff.ru

62

.IF условие1

...

.ELSEIF условие2

...

.ELSEIF условие3

...

.ELSE

...

.ENDIF

Если условие "истина", то выполняются команды соответствующего участка конструкции. Например, если условие2 "истина", то будет ассемблироваться участок между первой и второй директивой .ELSEIF. Если все три условия "ложь", то выполняются команды от .ELSE до .ENDIF.

Пример условной конструкции:

.IF AX == 7

mov bx,66h

.ELSE

mov bx,33h

.ENDIF

Представленный фрагмент эквивалентен следующему ассемблерному коду: cmp ax,7

jne NO mov bx,66h jmp EXIT NO:

mov bx,33h EXIT:

Конструкция цикла:

.WHILE условие

...

.ENDW

Пример:

.WHILE AX<99h add ax,10h

.ENDW

Представленный фрагмент эквивалентен следующему ассемблерному коду:

Label1:

add ax,10h

Label2:

cmp ax,99h jb Label1

В условиях можно использовать операторы из табл. 3.2. Например, можно записать такое условие:

.IF (eax==1 && ebx!=2)

; если eax = 1 и ebx не равно 2

.ENDIF