传递堆栈上的参数

Lyn*_*ite 4 assembly stack 68000 motorola

将参数传递给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
Run Code Online (Sandbox Code Playgroud)

Eli*_*sky 8

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

例如,在一些假设的装配中,当你在一个程序中.假设堆栈正在增长:

...
argument2
argument1
ret addr     <---- stack pointer 
Run Code Online (Sandbox Code Playgroud)

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

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


unw*_*ind 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
Run Code Online (Sandbox Code Playgroud)