Оператор
p(a, b, c)
транслируется в
PUSH a
PUSH b
PUSH c
CALL p
Это значит, что параметры, переданные процедуре p, находятся в стеке в обратном порядке, и, в предположении,
что каждый из параметров имеет размер два байта, а процедура является дальней,
после выполнения команды call
стек будет выглядеть следующим образом:
Адрес |
Значение |
SP+10 |
… |
SP+8 |
a |
SP+6 |
b |
SP+4 |
c |
SP+2 |
адрес возврата (CS) |
SP |
адрес возврата (IP) |
Кроме того, по соглашению PASCAL стек от параметров очищает сама процедура. Таким образом, процедура p будет иметь следующий вид:
p PROC FAR
PUSH BP
MOV BP, SP
a EQU [BP+8]
b EQU [BP+6]
C EQU [BP+4]
; Основная часть процедуры
; Регистр BP изменять нельзя,
; так как он адресует стековый кадр с параметрами
POP BP
RET 6
p ENDP
Тот же самый код большинство трансляторов способны порождать
по усложнённой форме директивы PROC
:
p PROC PASCAL, a:WORD, b:WORD, c:WORD
; Основная часть процедуры
; Регистр BP изменять нельзя,
; так как он адресует стековый кадр с параметрами
RET
p
ENDP
Последняя команда RET
будет автоматически заменена транслятором на
RET 6
Главный недостаток соглашения PASCAL заключается в сложности создания процедур с переменным количеством параметров. Действительно, количество параметров процедура определяет, как правило, по некоторому числу первых обязательных параметров. Но в случае переменного количества параметров процедура не будет знать положения первого из них в стеке.
Данная проблема решается с помощью обратного порядка передачи параметров в стек, в результате которого параметры оказываются в стеке в прямом порядке. Такое соглашения применяется в языке программирования C, а также PROLOG и ряде других. По данному соглашению стек от параметров очищает вызывающая процедура.
Оператор
p(a, b, c)
транслируется в
PUSH c
PUSH b
PUSH a
CALL p
ADD SP, 6 ; очистка стека
В прежних предположениях, после выполнения команды call
стек будет
выглядеть следующим образом:
Адрес |
Значение |
SP+10 |
… |
SP+8 |
c |
SP+6 |
b |
SP+4 |
a |
SP+2 |
адрес возврата (CS) |
SP |
адрес возврата (IP) |
Процедура p имеет следующий вид:
p PROC FAR
PUSH BP
MOV BP, SP
a EQU [BP+4]
b EQU [BP+6]
C EQU [BP+8]
; Основная часть процедуры
; Регистр BP изменять нельзя,
; так как он адресует стековый кадр с параметрами
POP BP
RET
p ENDP
Тот же самый код большинство трансляторов способны порождать
по усложнённой форме директивы proc
:
p PROC C, a:WORD, b:WORD, c:WORD
; Основная часть процедуры
; Регистр BP изменять нельзя,
; так как он адресует стековый кадр с параметрами
RET
p
ENDP
Соглашение C имеет ещё одно преимущество перед соглашением PASCAL. Стек не очищается от параметров вызываемой процедурой, поэтому, если необходимо вызвать несколько функций с одними и теми же параметрами, можно не заполнять стек каждый раз заново, то есть последовательность команд
p1(a, b, c)
p2(a, b, c)
можно транслировать не в
PUSH c
PUSH b
PUSH a
CALL p1
ADD SP, 6
PUSH c
PUSH b
PUSH a
CALL p2
ADD SP, 6
а в
PUSH c
PUSH b
PUSH a
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.