1

这是汇编代码:

    ldc 5 // a
    ldc 12 // b
    bsr sumsquare
    ajs -2 // delete parameters
    ldr RR // result on the stack
    stl 1 // store in a variable
    ....
    sumsquare:
    link 1 // 1 local variable
    ldl -3 // a
    ldl -3 // a
    mul // a*a
    ldl -2 // b
    ldl -2 // b
    mul // b*b
    add // a*a + b*b
    stl 1 // x
    ldl 1 // x
    str RR // store in RR (=result register)
    unlink 1
    ret

我想更改这段代码,将方法 sumsquare 的结果传递回堆栈。如果我是对的,我所要做的就是不要将其存储在 RR 中,而是将其立即存储在变量 a 和 b 所在的堆栈中。所以我必须使用其他东西而不是 str RR。

指令系统

这些都是这个简单的堆栈机器上所有可能的指令

4

1 回答 1

2

调用者压入5然后12,然后是返回地址,然后将控制权转移到sumsquare,它使用aMP-3(实际值5)和bMP-2(实际值12)的形式参数,位于 MP-1 的返回地址后面的堆栈上。从被调用者返回到调用者会将返回地址从堆栈中弹出,将实际参数512, 留在堆栈上,然后调用者将其从堆栈中弹出。

至少有三种可能的方法:

一种方法是让被调用者(函数)在函数结束时重新调整第一个形参的用途,方法是将返回值存储到a-3 处的形参中,然后让调用者仅从堆栈中弹出第二个实际参数而不是两个实际参数,在堆栈上留下一个返回值以正常使用(即通过表达式评估,例如通过算术或赋值)。这种方法需要对零参数函数进行特殊处理。

下一种方法是传递一个虚拟参数,为返回值保留空间。虚拟参数将首先传递,在5和之前12。被调用者,而不是将返回值存储到a-3 处的形式参数,该函数会将其存储到 -4 处的 dummy。然后,调用者将弹出两个实际参数5,并12按照原始参数从堆栈中弹出(但通常会消耗现在保存返回值的虚拟对象)。这种方法的优点是它更规则(允许零参数函数像所有其他函数一样工作)。

另一种方法是更改​​调用约定,以便被调用者(函数)从堆栈中删除自己的形式参数,只在堆栈中留下返回值。为了做到这一点,它必须 (1) 将返回值存储a在 -3 的形式参数中,然后 (2) 还将返回地址从其当前位置 -1 移动到b-2 位置,然后 ( 3)从堆栈中弹出返回地址的旧副本,并返回给调用者(弹出返回地址的新副本(又名b) 离开堆栈,只在堆栈上留下返回值)。在这种情况下,调用者不会弹出实际参数,因为这是由被调用者完成的。这种形式需要函数在其末尾做一些工作,但节省调用站点的空间;这可以通过观察通常比函数本身更多的函数调用来合理化(函数由多个调用者调用)。(有时会提供特殊的堆栈指令来更直接地执行此操作。)但是,这种形式对可变参数(可变参数函数)是不利的(如果不知道任何给定函数是否可以是可变参数,则将无法使用)。


通过为表达式求值和函数链接共享一个堆栈,这种洗牌是必要的。

在不同的架构中,两个独立的堆栈将允许在表达式堆栈上留下一个返回值,同时仍然能够弹出链接以返回给调用者——尽管两个堆栈会给硬件增加其他开销。

在另一种架构方法中,会有一个寄存器或累加器,这就是返回值的所在。

于 2019-09-19T14:01:08.087 回答