Способы передачи параметров. При вызове подпрограммы основная программа записывает фактические параметры (их значения или адреса) в стек, а процедура затем их оттуда извлекает. Пусть процедура Р имеет k параметров: P(a1,a2,...,ak). Будем считать, что параметры записываются в стек слева направо. Пусть каждый параметр имеет размер слова. Тогда команды основной программы, реализующие обращение к процедуре, будут следующими:
; обращение Р(a1,а2,...,ak)
PUSH a1
PUSH a2
...
PUSH ak
CALL P
(AB)...
На рис. 23 показано состояние стека после выполнения команд, т.е. на входе в процедуру.
Рис. 23. Содержимое стека при вызове подпрограммы.
Для доступа к элементам стека необходимо использовать регистр BP. Для этого в стеке следует сохранить содержимое BP, передать в него адрес вершины стека (содержимое регистра SP), а затем использовать выражение вида [BP+i] для доступа к параметрам процедуры. Таким образом, действия при входе в процедуру будут следующими:
; действия при входе в процедуру
P PROC ; объявление процедуры P
PUSH ВР ; сохранить ВР
MOV BP, SP ; BP - на вершину стека
... ; команды процедуры
После сохранения в стеке регистра ВР для доступа к параметрам процедуры следует использовать выражения: [BP+4] – для доступа к последнему параметру, [ВР+6] – для доступа к предпоследнему параметру и т.д. Например, запись последнего параметра в регистр АХ (AX:=ak) будет выполнен командой MOV АХ, [ВР+4] (рис. 24).
Рис. 24. Содержимое стека при выходных действиях подпрограммы.
После извлечения из стека параметров должны следовать команды самой процедуры. После их завершения процедура обязана восстановить состояние стека, например, командой MOV SP, BP. В результате к концу работы процедуры в вершине стека будет находиться прежнее значение регистра ВР. После восстановления ВР, в вершине стека будет находиться адрес возврата.
Очистку стека от параметров может выполнить основная программа. Для этого в ней после команды CALL P необходимо выполнить команду ADD SP,2*k. Однако такой способ не является оптимальным, т.к. обращений к процедуре, как правило, много и вызывать команду ADD придется многократно. Лучше возложить обязанность по очистке стека на саму процедуру.
Таким образом, процедура должна сначала очистить стек от параметров и только затем передать управление по адресу возврата. Чтобы упростить реализацию этих действий и существует расширенный вариант команды RET с непосредственным операндом. По этим инструкциям сначала из стека удаляется адрес возврата, затем стек очищается на указанное число байтов и далее выполняется переход по адресу возврата.
Операнд команды RET указывает, на сколько байт требуется очистить стек. Например, для очистки стека от k параметров, каждый из которых имеет размер слова, операнд должен быть равен 2*k. Адрес возврата в операнде не учитывается, т.к. команда RET считывает его до очистки стека. Команда RET эквивалентна RET 0, т.е. выполняет возврат без очистки стека. Таким образом, при выходе из процедуры действия должны быть следующими:
; действия при выходе из процедуры
POР ВР ; восстановить прежнее значение BP
RET 2*k ; очистка стека от k параметров-слов и возврат
ENDP
После возврата из процедуры состояние стека будет тем же, каким оно было до обращения к процедуре. Описанный способ передачи параметров универсален, и его можно использовать при любом числе параметров. Результат процедуры крайне редко передается через стек, и обычно для этого используются регистры.
Do'stlaringiz bilan baham: |