传递堆栈上的参数

时间:2010-04-09 05:28:21

标签: assembly stack motorola 68000

将参数传递给cpu堆栈上的函数时,

你把参数放在然后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 个答案:

答案 0 :(得分:8)

您不会从堆栈中“取消”参数,因为您不会弹出它们。您通常会在程序的入口点指定一个帧寄存器指向堆栈的顶部,并从帧指针的常量已知偏移量访问参数。然后你的索引只是“跳过”你知道的返回地址。

E.g。在一些假设的集​​会中,当你在一个程序中。假设堆栈正在增长:

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

所以只需在偏移argument1(假设为32位),sp+4偏移argument2等处访问sp+8,等等。由于这些调用约定是已知的,因此这些偏移量是在您的代码中进行硬编码,并且计算效率很高。

帧指针非常有用,因为您还将局部变量推送到堆栈,并且您不希望在不同位置更改参数索引,因此帧指针在整个过程执行期间提供稳定的锚点。 / p>

答案 1 :(得分:6)

没有

被调用者(目标函数)通常不负责删除自己的参数。呼叫者把它们放在那里,并且是最了解如何移除它们的人。

在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

答案 2 :(得分:3)

不,没有必要从堆栈中弹出参数来查看它们;通常的程序是使用“帧指针”寄存器,如@eli所说。事实上,68k甚至有一条指令(LINK),它旨在促进:它是一条指令,(a)保存前一帧指针,(b)将当前堆栈指针复制到帧指针,以及(c)将堆栈指针递减指定的量,以便为局部变量留出空间。

这是一个example of C code and the corresponding 68000 assembler