【问题标题】:ARM: What to do with the stack pointer?ARM:如何处理堆栈指针?
【发布时间】:2017-05-25 10:45:42
【问题描述】:

我从教授那里得到了以下 ARM 汇编代码。 我不明白为什么我需要将堆栈指针移动到 r1 以及究竟会发生什么。

我从讲座中知道,...

堆栈指针指向堆栈上最后写入的值。

指向总是意味着存储地址吗? 我设法让代码工作。但我想提高代码质量并了解发生了什么。我也不允许在程序的任何地方使用算术运算。 我也试过调试器。但我只知道如何从那里观看节目计数器。 我用过

info registers sp pc

disas

我搜索了调试器的所有选项,但找不到有用的东西。

在堆栈指针寄存器中存储-我猜-一些地址值。

// scan for users answer 'y'
ldr     r0, =charplace
mov     r1, sp              @ ???
bl      scanf               @ Scan user's answer
ldr     r1, =yes            @ Put address of 'y' in r1
ldrb    r1, [r1]            @ Load the actual character 'y' into r1

在主函数开始时我这样做:

        .global main
main:                   
     push   {r4 - r7, lr}   @ copy values of these reg on top of the stack
     sub     sp, sp, #4     @ needs to be replaced ! TODO

最后是这样的:

end: add    sp, sp, #4      @ needs to be replaced ! TODO
     pop    {r4 - r7, pc}   @ copy values from the top of the stack back into these registers

【问题讨论】:

  • 可以通过注释掉 add/sub 并更改有关 push/pop 指令的某些内容来解决 TODO。如果你的调试器恰好是gdb,你可以试试layout asm layout regs,虽然我不确定它是否能在你的目标平台上工作。
  • 是的,sp 寄存器中的值通常是内存中的有效地址,它是为“堆栈”保留的(它只是普通内存和指向它的指针,push/pop 功能可以排序原则上通过将值存储/加载到内存+更新指针来模拟,push/pop 写起来更短,而且它们通常是原子的(或者至少更容易通过某种lock 前缀使它们成为原子))
  • 好的。感谢您的提示。我试过layout asmlayout regs。它一开始看起来不错,但在短时间内就坏了。我不知道要更改说明。这就是我问的原因。 :3
  • 好吧,如果您了解push/pop 与多个寄存器的工作原理,您一定会弄清楚如何使它们也对sp 执行额外的+-4。虽然它不是add/sub 的完全替代品,因为它会产生额外的副作用,所以您还必须考虑使用调用约定,考虑哪种调整会产生无害的副作用。只需查看 ARM 文档以了解这些指令的详细信息,并想象它们是如何工作的,以及 sp 和其他寄存器会发生什么。
  • main.s: Assembler messages: main.s:22: Warning: if writeback register is in list, it must be the lowest reg in the list main.s:144: Warning: writeback of base register when in register list is UNPREDICTABLE

标签: pointers assembly arm raspberry-pi3


【解决方案1】:

sub sp, sp, #4 为缓冲区分配 4 个字节的空间。对于一个完整的降序堆栈,sp 将指向该缓冲区的开头,其他 3 个字节当然位于sp+1sp+2sp+3。将sp 移动到r1 的原因是scanf 需要缓冲区地址作为第二个参数,而r1 用于传递它。

gdb 中,您可以使用x 命令检查内存,以查看您可以执行的堆栈,例如x/4x $sp。有关格式说明符,请参阅 help x

【讨论】:

  • 谢谢。 x 似乎很有用。但它现在对我的帮助不大,因为我不知道在记忆中要检查什么。 :)
  • 您的回答非常有用。为什么scanf 需要一个缓冲区,但调用我的一个函数使得没有必要在堆栈下方创建一些空间?
  • 您知道scanf 的工作原理吗?在 C?您意识到它需要空间来存储转换结果。那是你分配的。
  • 不,这是我们不学习 C 的问题。我们在 1. 和 2. 学期学习汇编 (MMIX)。现在是我的 3. 组装学期,我对 C 的了解仍然不多。是的,但是好的,我会接受它需要一些空间来返回结果。用户输入。因此需要4个字节但不能用一个寄存器来传送它的返回值,因为它不是一个汇编程序。有道理。
猜你喜欢
  • 2014-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-26
  • 2021-12-26
  • 1970-01-01
  • 2013-01-20
相关资源
最近更新 更多