Результаты функции в Турбо Паскале
В зависимости от типа результата функции Турбо Паскаля возвращают свои результаты различными способами.
Результаты функции скалярного типа
Результаты функции скалярных типов возвращаются в регистрах центрального процессора (ЦП). Байтовые значения возвращаются в регистре 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 MyInt DW ? ; зарезервировать слово MyByte DB ? ; зарезервировать байт . . . DATA ENDS
Переменных, выделяемых Турбо Ассемблером в сегменте глобальных данных, касаются два важных ограничения. Во-первых, эти переменными являются "частными", они недоступны программе Турбо Паскаля (хотя вы можете передавать указатели на них). Во-вторых, они не могут быть предварительно инициализированы, как типизованные константы. Оператор:
MyInt DW 42 ; это не инициализирует MyInt значением 42
не вызовет ошибки при компоновке модуля с программой Турбо Паскаля, однако MyInt при выполнении программы не будет иметь значение 42.
Эти ограничения можно обойти, описав переменные или типизованные константы Турбо Паскаля с помощью директивы EXTRN, что сделает их доступными Турбо Ассемблеру.
Выделение временной памяти
В ваших программах на Турбо Паскале можно выделять также временную память (локальные переменные) в стеке на время выполнения каждого вызова. Перед возвратом управления эта память должна быть освобождена, а значение регистра BP восстановлено. В следующем примере процедура MyProc резервирует пространство для двух целых переменных a и b:
CODE SEGMENT ASSUME CS:CODE MyProc PROC FAR ; procedure MyProc(i : integer); PUBLIC MyProc LOCAL a : WORD, b : WORD = LocalSpace ; a в [bp-2] b - в [bp-4] i equ word ptr [bp+6] ; параметр i находится над сохраненным BP и адресом возврата push bp ; нужно сохранить BP вызывающей программы mov bp,sp ; теперь BP указывает на вершину стека sub sp,LocalSpace ; зарезервировать пространство для двух слов mov ax,42 ; загрузить в AX начальное значение A mov a,ax ; и в A xor ax,ax ; очистить регистр AX mov b,ax ; инициализировать B нулем mov b,ax ; выполнить нужные действия . . . mov sp,bp ; восстановить исходное ; значение SP mov bp ; восстановить исходное ; значение регистра BP ret 2 MyProc ENDP CODE ENDS END
Примечание: Директива Турбо Ассемблера LOCAL используется для создания идентификаторов и выделения пространства для локальных переменных.
Оператор:
LOCAL a : WORD, b : WORD = LocalSpace
на время выполнения процедуры присваивает идентификатору a значение [BP-2], идентификатору b - значение [BP-4], а идентификатору LocalSpace - число 4 (размер области локальных переменных). Поскольку нет соответствующего оператора для создания идентификаторов, ссылающихся на параметры, вы должны использовать присваивание i значения [BP+6].
Более разумный способ инициализации локальных переменных заключается в том, чтобы вместо уменьшения SP занести в стек их значения. Таким образом, вы должны заменить SUB SP,LocalSpace инструкциями:
mov ax,42 ; получить начальное значение для a push ax ; занести его в a xor ax,ax ; обнулить AX push ax ; и занести 0 в b
Если вы используете этот способ, нужно внимательно отслеживать стек! Не следует ссылаться на идентификаторы a и b перед тем, как они занесены в стек.
Другой вид оптимизации предусматривает использование инструкции PUSH CONST для инициализации локальных переменных (ее можно использовать при наличии процессором 80186, 80286 и 80386), или сохранение BP в регистре вместо занесения его в стек (если есть неиспользованные регистры).
1 2 3 4 5 6 7 8
8 8 8
| |