【发布时间】:2021-06-01 15:20:51
【问题描述】:
我的教授布置了一个家庭作业,事情是这样的。这是 ARM 程序集,想象这是一个空降序堆栈。这意味着内存地址从高地址移动到低地址,空意味着堆栈指针指向堆栈上方的空白空间。在此示例中,地址位于括号中。我会用 | |为空的空间。 TOS 是栈顶,SP 是栈帧的当前位置。
|___| (80)
|___| (84)
|___| (88)
|___| SP (92)
|___| TOS (96)
|___| (100)
这是有问题的代码。我会解释我认为在每一行之后会发生什么
-
STMED sp!, {fp,lr}(FP为R11,LR为R13。因为低位寄存器进入低位地址,所以当前值FP存放在88,LR存放在92。堆栈是ED堆栈,所以SP在84 ,FP上方的一个点) -
MOV fp,sp(FP现在指向与SP相同的位置,84。FP的先前值存储在位置88) -
SUB SP,SP,#4(SP 指向 80) -
STR R3, [fp, #12](FP为84,所以R3存储在84+12等于96,替换旧TOS) -
STR R6, [fp,#-4](R6存储在84-4即80)
所以这是我的逻辑,对我来说很有意义,但我的教授说我错了。她说我不应该使用 FP 指向的位置,而是放在堆栈上的 FP 的值(位于位置 88)。这意味着 R3 将存储在点 100,而 R6 将存储在点 84。她坚信这是正确的,并表示帧指针一旦放入堆栈就不能更改,它是堆栈帧的基础。我明白这一切,但我不明白她的逻辑。我们将值存储在堆栈中,然后将其更改为指向其他内容。为什么我们仍然使用旧值?谁能给我解释一下?
【问题讨论】:
-
我们不能也不应该从这些信息中知道放入堆栈的 FP 的值。该 FP 属于调用者,他可能已经设置了 FP,也可能没有设置 FP。即使他们这样做了,他们的 FP 也可能指向更高的堆栈。此外,这个函数可以被不同的调用者调用。所以,旧的 FP 和新的 FP 彼此仅相差 4,并且在这种情况下总是彼此相差 4,并不对我有意义。 (两种解释的差异4似乎更像是ED和FD的差异。)
-
@ErikEidt 在这种情况下,堆栈的寻址和 FP 的值并不重要,因为它不是一个实际的程序,而是一个测试我们对堆栈理解的示例。 4 的差异对我来说也没有意义,但我想象当我们将旧的 FP 存储在位置 88 时,我们可能会将返回地址存储到堆栈上的另一个点,然后新的 SP 是我们的偏移量用于导航堆栈。我不太明白,所以如果我离开了,我很抱歉。
标签: assembly arm stack callstack stack-frame