【问题标题】:Reading stack pointer value in ARM在ARM中读取堆栈指针值
【发布时间】:2019-07-15 00:21:49
【问题描述】:

我正在尝试将 SP 寄存器的值存储到 C 中的变量中,这是我的代码:

int address = 0;
asm volatile ("STR sp, [%0]\n\t"
     : "=r" ( address)
     );

但在执行此代码后,操作系统会在屏幕上打印“Segmentation fault”消息并终止程序。谁能给我一个解决问题的建议?

【问题讨论】:

  • 由于您指定了注册目的地,所以不要使用STR ...只需MOV %0, sp
  • 通常你可以只取本地变量的地址来获取当前函数堆栈帧中某处的地址。或使用__builtin_frame_address(0)gcc.gnu.org/onlinedocs/gcc/Return-Address.html。但是,是的,使用内联汇编你肯定只想要mov%0。一般使用intptr_t address,而不仅仅是int,来保存指针,虽然是在32位ARM上int可以保存指针。
  • 对于内联 asm 更好的版本:register void* address __asm__("sp"); __asm__ __volatile__("" : "=r" (address));
  • @Jester:你会认为这很好,但 ARM gcc 实际上会通过首先执行mov sp, r3 来破坏 SP。 godbolt.org/z/-DEbAD。我在玩"+r"(sp) 作为Print out value of stack pointer 的可能答案 - 使用"+r" 而不是"=r",我们得到 mov r3,sp / mov sp,r3 / mov r0,sp 所以它在 ARM 上仍然很糟糕。但它适用于 x86,它允许 GCC 将 RSP 直接存储到内存目标,如果需要,无需使用 reg-reg mov
  • @PeterCordes 看起来像回归。我的 gcc 4.3.3 工作正常。

标签: c assembly arm inline-assembly


【解决方案1】:

您甚至不应该触摸内联汇编中的堆栈指针。这是禁忌!!!

你不应该一开始就这样做。把它留给编译器。

如果您没有更改堆栈指针或将任何内容写入堆栈,它可能会起作用,您只是使用了错误的指令。

你想做什么:将堆栈指针复制到一个 32 位寄存器。

您所做的:将堆栈指针本身存储到地址 0。==> 分段错误。

STR sp, [%0]\n\t 替换为mov %0, sp\n\t

【讨论】:

  • address = 0 初始化程序可以被优化掉,将任何垃圾留在寄存器中。这是一个"=r" 仅输出约束,而不是"+r",因此任何早先对address 的分配在那时都已失效。所以商店地址很可能是一些垃圾,而不是 0。
猜你喜欢
  • 1970-01-01
  • 2011-10-26
  • 2014-11-28
  • 1970-01-01
  • 1970-01-01
  • 2015-11-16
  • 2013-01-20
  • 1970-01-01
  • 2013-12-02
相关资源
最近更新 更多