Вопрос

Когда вы передаете параметры на функцию в стеке ЦП,

Вы помещаете параметры в то, что 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) уменьшает указатель стека на указанную сумму, чтобы оставить место для локальные переменные.

Вот а Пример C кода и соответствующий ассемблер 68000.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top