- •Язык ассемблера и программирования Глава 1. Директивы языка ассемблера Директива segment
- •Директива group
- •Директива assume
- •Assume сегментный_регистр : имя [, ...]
- •Директива Proc
- •Директива macro
- •Оформление программ в виде отдельных модулей
- •Передача параметров в подпрограмму
- •Директивы упрощенного описания сегментов Директива model
- •Описание
- •Вызов процедур с использованием кадра стека
- •Глава 2. Вывод информации на терминал в текстовом режиме Вывод символьной строки. Модуль puts.
Описание
LOCAL LcalArray : byte : 100, LocalCount : word = AUTO_SIZE
определяет автоматически размещаемые переменные LocalArray и LocalCount. Значение метки LocalArray устанавливается эквивалентным [BP-100], а LocalCount - [BP-102], а в тексте процедуры можно обращаться по этим символьным именам. AUTO_SIZE - общее количество байтов, необходимое для размещения локальных переменных. Это значение необходимо вычесть из SP для выделения места в стеке под размещение указанных переменных.
Пример использования директивы LOCAL:
...
_TestSub PROC
LOCAL LocalArray:byte:100,LocalCount:word=AUTO_SIZE
push bp
mov bp,sp
sub sp,AUTO_SIZE
mov [LocalCount],10
...
mov cx,[LocalCount]
mov al,’A’
lea bx,[LocalArray]
FillLoop:
mov [bx],al
inc bx
loop FillLoop
mov sp,bp
pop bp
ret
_TestSub ENDP
...
Другим средством Turbo Assembler, предназначенным для улучшения интерфейса , является директива ARG. Директива ARG имеет следующий формат:
ARG аргумент [, аргумент] ... [= идентификатор]
[RETURNS аргумент [, аргумент ]]
Синтаксис параметра аргумент точно такое же как и для аргумента директивы LOCAL. В Turbo Assembler версии 3.2 или более поздней можно задать значение счетчика2, используя ключевое слово ?, которое указывает на переменное количество аргументов, предаваемых в процедуру. Например, если имеется следующее описание аргументов:
ARG tmp: WORD: ?
то аргумент tmp может состоять из любого количества слов.
Аргументы и локальные переменные адресуются в процедуре относительно регистра BP. Например:
...
func PROC NEAR
ARG a:WORD, b:DWORD:4, c:BYTE = d
LOCAL x:DWORD, y:WORD:2 = z
...
определяет a - [BP+4], b - как [BP+6], c - как [BP+14], d - как 20 (так как длина с по умолчанию равна 2) ; x - как [BP-2], y - как [BP-6] z - как 8.
Директива RETURN указывает на параметры, возвращаемые процедурой.
Директивы упрощенного описания сегментов Директива model
Директива MODEL позволяет задавать в программе одну из нескольких стандартных моделей сегментаций. Кроме того, ее можно использовать для указания языка в процедурах программы.
Синтаксист директивы MODEL:
.MODEL[модификатор]модель_памяти [имя_кодового_сегмента]
[,[модификатор_языка] язык][,модификатор]
Модель памяти может принимать одно из следующих значений:
TINY, SMALL, MEDIUM, COMPACT, LARGE, HUGE, TCHIGE, TPASCAL, FLAT.
Директивы упрощенного описания сегментов употребляются в программе после выбора модели памяти директивой .MODEL.
В тексте программного модуля директивы упрощенного описания могут располагаться в произвольном порядке: Turbo Assembler компонует все части с одинаковыми именами в один сегмент.
Директива |
Описание |
.CODE[имя] |
Начало или продолжение кодового сегмента модуля.Для модели с типом FAR можно задать имя ,которое становится действующим именем сегментa. B этом случае нельзя иметь более одного кодового сегмента в модуле. |
.DATA |
Начало или продолжение сегмента данных, инициалиированных по умолчанию. |
.CONST |
Начало или продолжение сегмента постоянных данных модуля.. |
.DATA? |
Начало или продолжение сегмента данных, неинициированных по умолчанию. |
.STACK[размер] |
Начало или продолжение сегмента стека программного модуля. Необязательный параметр размер указывает объем памяти, отводимой под стек. По умолчанию Turbo Assembler устанавливает размер стека 1К. |
Использование директив упрощенного описания сегментов создает переменные, которые описывают детали выбранного сегмента. К значениям этих переменных можно обращаться для получения информации о том или ином сегменте. В следующей таблице приведено описание этих идентификаторов:
Идентификатор |
Значение |
@code |
Сегмент или группа ,назначенные CS. |
@data |
То же DS. |
@stack |
Сегмент или группа ,назначенные SS. |
;----------------------------------------------------------------------------------------------------
;get_str1.asm Главная программа для вызова функции gets1.asm. Вызов ;функции:
; int gets1(char *buf);
; Здесь *buf- адрес буфера. Функция возвращает число прочитанных байт.
;----------------------------------------------------------------------------------------------------
LBUF=82
EXTRN gets1:near
.MODEL small
.DATA
string db LBUF dup(?) ;Буффер для приема строки
.STACK 100h
.CODE
beg proc far
push ds
sub ax,ax
push ax
mov ax,@data ; В ax адрес сегмента данных
mov ds,ax
mov ax,offset string ; Передача адреса string через стек
push ax
call gets1
add sp,2 ; Очистка кадра стека
ret
beg ENDP
END beg
Рис. 1.12. Головная программа для вызова модуля gets1.asm
В программе на рис. 1.12 используется передача параметра через стек.
;----------------------------------------------------------------------------------------------------
;gets1.asm
; Функция чтения строки. Прототип:
; int gets(char* p_str);
; По адресу p_str помещается строка в ASCIIZ. Функция возвращает число ;прочитаных символов.
;----------------------------------------------------------------------------------------------------
L_VAL=134
.MODEL small
.CODE
PUBLIC gets1
gets1 PROC near
ARG p_str:word ;адрес строки вызывающего модуля
LOCAL string:byte:L_VAL,p_ds:word=L_PER
;string:byte:L_VAL буфер для приема строки, используемый при вызове функции ;0ah прерывания int 21h
push bp
mov bp,sp
sub sp,L_PER ;резервирование места для локальных переменных
mov ax,bp
sub ax,L_VAL
push ds
push dx
mov p_ds,ds
mov dx,ax ;установка регистров ds:dx на начало буфера
mov ax,ss
mov ds,ax
mov string,L_VAL ;в первый байт записывается максимальная длина ;буфера
mov ah,0ah
int 21h
push si
push di
mov si,dx ;загрузка регистра si
add si,2 ;регистры ds:si используются при вызове lodsb
mov ax,p_ds ;загрузка регистров es:di, которые используются при
mov es,ax ;вызове функции stosb
mov di,p_str
a: lodsb
cmp al,0dh ;прверка на конец строки
jz b
stosb
jmp a
b: xor al,al
stosb ;запись нуль-терминатора
xor ah,ah
mov al,string+1 ;в ax - числи считанных байтов
pop di
pop si
pop dx
pop ds
mov sp,bp
pop bp
ret
gets1 endp
end
Рис. 1.13. Вызываемый модуль gets1.asm.
В приведенной на рис. 1.13 программе для ввода строки из клавиатуры используется функция 0ah лрерывания int 21h. Эта функция помещает вводимую строку в буфер, место для которого выделено в стеке. Затем эта строка передается в вызывающую программу в формате ASCIIZ.
;----------------------------------------------------------------------------------------------------
;get_str2.asm Главная программа для вызова функции gets2.asm. Вызов ;функции:
; int gets2(char *buf);
; Здесь *buf- адрес буфера. Функция возвращает число прочитанных байт.
; В этом примере в директиве .MODEL указан язык Си, поэтому в модуле будут ;выполняться соглашения языка Си по умолчанию.
;----------------------------------------------------------------------------------------------------
LBUF=82
EXTRN _gets:near
.MODEL small,C
.DATA
string db LBUF dup(?)
.STACK 100h
.CODE
beg proc far
push ds
sub ax,ax
push ax
mov ax,@data
mov ds,ax
mov ax,offset string
push ax
call _gets
add sp,2
ret
beg ENDP
END beg
Рис. 1.14. Вызывающая программа, поддерживающая соглашения языка Си по умолчанию.
Следует обратить внимание на то, что имя вызываемого модуля _gets содержит символ подчеркивания, что согласуется с соглашениями, принятыми для языка Си.
Описание модуля можно упростить, если воспользоваться директивами .STARTUP и .EXIT. Директива .STARTUP инициализирует регистры DS, SS и SP. Идентификатор @Startup автоматически помещается перед начальным кодом, генерируемым директивой STARTUP, и представляет собой метку ближнего типа, указывающую на начало программы. Для автоматического создания в программе кода завершения предназначена директива .EXIT. Синтаксис этой директивы следующий:
.EXIT [код_возврата]
Необязательный параметр код_возврата - выражение, результат вычисления которого возвращается операционной системе по завершения работы программы. Пример применения этих директив приведен на рис. 1.15.
LBUF=82
EXTRN _gets:near
.MODEL small,C
.DATA
string db LBUF dup(?)
.STACK 100h
.CODE
beg proc far
.STARTUP
mov ax,offset string
push ax
call _gets
add sp,2
.EXIT
beg ENDP
END beg
Рис.1.15.
