 |
Покажем, как будет выглядеть пример предыдущего раздела,
если переписать его, используя директиву ARG:
CODE SEGMENT
ASSUME CS:CODE
MyProc PROC FAR ; procedure MyProc(i,j : integer);
; external;
PUBLIC MyProc
ARG j : WORD, i : WORD = RetBytes
push bp ; нужно сохранить BP вызывающей
; программы
mov bp,sp ; BP теперь указывает на вершину
; стека
mov ax,i ; адресуемся к i через BP
.
.
.
Директива ARG Турбо Ассемблера создает локальные идентифика-
торы для параметров i и j. На время выполнения процедуры строка:
ARG j : WORD, i : WORD = RetBytes
автоматически приравнивает идентификатор i к [WORD PTR BP+6],
Турбо Ассемблер 3.0/tasm/#2-2 = 130 =
идентификатор j к [WORD PTR BP+8], а идентификатор RetBytes - к
числу 4 (размеру в байтах блока параметров). В значениях учитыва-
ется и занесенное в стек значение BP, и размер адреса возврата:
если бы процедура MyProc имела ближний тип, то i было бы прирав-
нено к значению [BP+4], j - к [BP+6], а RetBytes также было бы
равно 4 (в любом случае процедура MyProc может завершить выполне-
ние с помощью инструкции RET RetBytes).
При использовании директивы ARG нужно помнить, что параметры
должны перечисляться в обратном порядке. Последний параметр про-
цедуры или функции Турбо Паскаля нужно размещать в директиве ARG
первым и наоборот.
Относительно использования директивы ARG с Турбо Паскалем
можно сделать еще одно замечание. В отличие от других языков,
Турбо Паскаль всегда заносит в стек параметр-значение размером в
байт, как 16-битовое слово. При этом сообщить Турбо Ассемблеру о
дополнительном байте должны вы. Предположим, например, что вы на-
писали функцию, описание которой в Паскале выглядит следующим об-
разом:
function MyProc(i, j : char) : string; external;
Директива ARG для этой функции должна была бы выглядеть так:
ARG j: BYTE: 2, i:BYTE: 2 = RetBytes RETURN result: DWORD
Здесь 2 после каждого аргумента необходимо указывать для то-
го, чтобы сообщить Ассемблеру, что каждый идентификатор заносится
в стек, как массив из 2 байт (где, в данном случае, младший байт
каждой пары содержит полезную информацию).
В функции, возвращающей строковое значение (как данная функ-
ция), параметр RETURNS в директиве ARG позволяет вам определить
переменную, приравненную к тому месту в стеке, которое указывает
на временный результат функции. Переменная в RETURNS на размер (в
байтах) блока параметров.
Турбо Паскаль и директива .MODEL
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Директива .MODEL с параметром TPASCAL задает упрощенную сег-
ментацию, модель памяти и языковую поддержку. Обычно используется
большая модель памяти (large) Ранее мы уже видели, что нужно сде-
лать в программах Ассемблера, чтобы можно было использовать про-
цедуры и функции Паскаля. Преобразуем пример, используя в нем ди-
рективы .MODEL и PROC:
.MODEL large, PASCAL
.CODE
MyProc PROC FAR i:BYTE,j:BYTE result:DWORD
PUBLIC MyProc
mov ax,i
Турбо Ассемблер 3.0/tasm/#2-2 = 131 =
.
.
.
ret
Заметим, что теперь не нужно задавать параметры в обратном
порядке. Не требуется также масса других операторов. Использова-
ние в директиве .MODEL ключевого слова PASCAL задает использова-
ние соглашений Паскаля, определяет имена сегментов, выполняет
инструкции PUSH BP и MOV BP,SP и задает также возврат с помощью
инструкций POP BP и RETn (где n - число байт параметров).
Использование другого базового или индексного регистра
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Второй способ доступа к параметрам состоит в использовании
для получения этих параметров другого базового или индексного ре-
гистра (BX, SI или DI). Нужно однако помнить, что по умолчанию
сегментным регистром для них является регистр DS, а не SS. Поэ-
тому для их использования вам придется применять префикс переоп-
ределения сегмента.
Приведем пример использования для получения параметров ре-
гистра BX:
CODE SEGMENT
ASSUME CS:CODE
MyProc PROC FAR ; procedure MyProc(i,j : integer);
PUBLIC MyProc
j EQU WORD PTR SS:[BX+4] ; j находится над сохраненным
; BP и адресом возврата
i EQU WORD PTR SS:[bp+8] ; i располагается над j
mov bx,sp ; BX теперь указывает на вершину
; стека
mov ax,i ; адресуемся к i через BX
.
.
.
В тех программах, где нет большого числа ссылок на парамет-
ры, такой метод позволяет сэкономить время и место. Почему? Пото-
му, что в отличие от BP, регистр BX не требуется восстанавливать
в конце программы.
Результаты функции в Турбо Паскале
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
В зависимости от типа результата функции Турбо Паскаля возв-
ращают свои результаты различными способами.
Результаты функции скалярного типа
Результаты функции скалярных типов возвращаются в регистрах
Турбо Ассемблер 3.0/tasm/#2-2 = 132 =
центрального процессора (ЦП). Байтовые значения возвращаются в
регистре AL, значения размером в 2 байта - в регистре AX,
4-байтовые значения - в паре регистров DX:AX (старшее слово нахо-
дится в регистре DX).
Результаты функции вещественного типа
Результаты используемого в Турбо Паскале 6-байтового прог-
раммно эмулируемого вещественного типа возвращаются в трех ре-
гистрах ЦП. Наиболее значащее (старшее) слово возвращается в DX,
среднее - в BX, а наименее значащее - в AX.
Результаты функции типов сопроцессора 8087
Результаты типов, использующихся сопроцессором 8087, возвра-
щаются в регистре вершины стека ST(0) (или просто ST).
Результаты функции строкового типа
Результаты строкового типа возвращаются во временной рабочей
области, выделяемой Турбо Паскалем перед вызовом. Указатель даль-
него типа на эту область заносится в стек перед занесением перво-
го параметра. Заметим, что этот указатель не является частью
списка параметров.
Примечание: Не удаляйте из стека полученный в резуль-
тате указатель, так как Турбо Паскаль ожидает, что после
вызова он будет доступен.
Результаты функции типа указатель
Результаты указатель возвращаются в паре регистров DX:AX
(сегмент:смещение).
Выделение пространства для локальных данных
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Ваши программы, написанные на Турбо Ассемблере, могут выде-
лять пространство для своих собственных переменных, как постоян-
ных (статических), то есть сохраняющихся в промежутке между вызо-
вами, так и для временных (которые после вызова будут потеряны).
Оба этих случая обсуждаются в следующих разделах.
Выделение статической памяти
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Турбо Паскаль позволяет в программах Турбо Ассемблера резер-
вировать пространство для статических переменных в сегментах гло-
бальных данных (DATA или DSEG). Чтобы выделить это пространство,
можно просто использовать такие директивы, как DB, DW и т.д. Нап-
ример:
DATA SEGMENT PUBLIC
Турбо Ассемблер 3.0/tasm/#2-2 = 133 =
MyInt DW ? ; зарезервировать слово
MyByte DB ? ; зарезервировать байт
.
.
.
|