Передача параметров в стек - PullRequest
4 голосов
/ 09 апреля 2010

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

Вы помещаете параметры, затем 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

Ответы [ 3 ]

8 голосов
/ 09 апреля 2010

Вы не «снимаете» параметры из стека, в том смысле, что вы их не выталкиваете. Вы обычно назначаете регистр кадра, чтобы он указывал на вершину стека в точке входа в процедуру, и обращаетесь к параметрам с постоянными, известными смещениями из указателя кадра. Тогда ваш индекс просто «пропускает» обратный адрес, который, как вы знаете, есть.

например. в какой-то гипотетической сборке, когда вы находитесь в процедуре. Предположим, стек растет:

...
argument2
argument1
ret addr     <---- stack pointer 

Так что просто получите argument1 со смещением sp+4 (при условии 32-битного), argument2 со смещением sp+8 и т. Д. Поскольку эти соглашения о вызовах известны, эти смещения жестко закодированы в вашем коде и являются эффективно вычислять.

Указатель кадра очень полезен, поскольку вы также помещаете локальные переменные в стек и не хотите, чтобы индексирование параметров изменялось в разных местах, поэтому указатель кадра обеспечивает стабильную привязку на протяжении всего выполнения процедуры.

6 голосов
/ 09 апреля 2010

номер

Вызываемый объект (целевая функция) обычно не несет ответственности за удаление своих собственных аргументов. Звонящий положил их туда, и тот, кто лучше всех знает, как их удалить.

А на 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
3 голосов
/ 09 апреля 2010

Нет, нет необходимости извлекать параметры из стека, чтобы посмотреть на них; обычная процедура - использовать регистр «указатель кадра», как говорит @eli. На самом деле, 68k даже имеет инструкцию (LINK), предназначенную для облегчения этого: это одна инструкция, которая (а) сохраняет указатель предыдущего кадра, (б) копирует текущий указатель стека в указатель кадра и (с) ) уменьшает указатель стека на указанную величину, чтобы оставить место для локальных переменных.

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

...