Передача параметров на стеке
Вопрос
Когда вы передаете параметры на функцию в стеке ЦП,
Вы помещаете параметры в то, что JSR ставит обратный адрес в стеке. Так что это означает, что в вашей функции вы должны взять верхний элемент стека (обратный адрес), прежде чем вы можете взять остальные)
Возвращаемое значение хранится Конвенцией в регистре D0
.
Например, следующий правильный способ пойти в это:
...
|Let’s do some addition with a function,
MOVE.L #4, -(SP)
MOVE.L #5, -(SP)
JSR add
|the result of the addition (4+5) is in D0 (9)
...
add:
MOVE.L (SP)+, A1 |store the return address
|in a register
MOVE.L (SP)+, D0 |get 1st parameter, put in D0
MOVE.L (SP)+, D2 |get 2nd parameter, put in D2
ADD.L D2, D0 |add them,
|storing the result in D0
MOVE.L A1, -(SP) |put the address back on the
|Stack
RTS |return
Решение
Нет.
Callee (целевая функция), как правило, не несет ответственности за устранение собственных аргументов. Звонящий поставил их туда, и тот, кто лучше всего знает, как их удалить.
И на 68000 легко читать, используя относительное смещение в стеке, нет необходимости физически удалять (поп) аргументы из стека. Это происходит вокруг проблемы с «двойным буфером» обратный адрес довольно красиво.
Итак, ваш код должен прочитать что-то вроде этого:
MOVE.L #4, -(SP)
MOVE.L #5, -(SP)
JSR add
ADDQ.L #8, SP |remove the arguments from the stack, both at once.
...
add:
MOVE.L 4(SP), D0 |get 1st parameter, put in D0
ADD.L 8(SP), D0 |add the 2nd parameter
RTS |return
Другие советы
Вы не «снимаете» параметры из стека, в том смысле, что вы не их не поп. Обычно вы назначаете регистр кадров, чтобы указать на верхнюю часть стека в точке записи в процедуру, и получить доступ к параметрам при постоянных, известных смещениях из указателя кадра. Затем ваш индекс просто «пропускает» обратный адрес, который вы знаете, есть там.
Например, в какой-то гипотетической сборке, когда вы находитесь в процедуре. Предположим, что стек растет вниз:
...
argument2
argument1
ret addr <---- stack pointer
Так просто доступ argument1
на смещении sp+4
(при условии 32-битного), argument2
на смещении sp+8
, И т. Д. С тех пор, как эти конвенции вызова известны, эти смещения жестко закодированы в вашем коде и эффективны для вычисления.
Указатель кадра очень полезен, поскольку вы также продвигаете локальные переменные для стека, и вы не хотите, чтобы индексирование параметров изменяться в разных местах, поэтому указатель кадра обеспечивает стабильный якорь на протяжении всего выполнения процедуры.
Нет, нет необходимости поп-параметров от стека, чтобы посмотреть на них; Обычная процедура заключается в использовании «указатель кадров», как говорит @eli. На самом деле, 68К даже имеет инструкцию (LINK
) Это предназначено для облегчения того, что: это однозначное обучение, которое (а) сохраняет предыдущий указатель кадра, (b) копирует текущий указатель стека на указатель кадра, а (c) уменьшает указатель стека на указанную сумму, чтобы оставить место для локальные переменные.