ARM的指令反汇编

时间:2014-01-23 14:41:19

标签: gdb arm raspberry-pi raspbian

我刚刚设置了一个覆盆子pi机器,并尝试对以下代码进行逆向工程。

#include<stdio.h>
int main() {
printf("this is a test\n");
}

在大多数情况下,gdb中的以下反汇编似乎都有意义。

   0x000083c8 <+0>: push    {r11, lr}
   0x000083cc <+4>: add r11, sp, #4
   0x000083d0 <+8>: ldr r0, [pc, #8]    ; 0x83e0 <main+24>
   0x000083d4 <+12>:    bl  0x82ec <puts>
   0x000083d8 <+16>:    mov r0, r3
   0x000083dc <+20>:    pop {r11, pc}
   0x000083e0 <+24>:    andeq   r8, r0, r4, asr r4
  1. 但是,我不明白为什么0x000083e0处的指令存在。那条指令甚至是主要功能的一部分吗?不会将在0x000083c8处推送的值弹出到pc中,立即将控制转移到其他位置吗?
  2. 我也尝试在0x000083e0设置断点 - 我似乎得到了一个非常奇怪的SEGFAULT。为什么会这样?

2 个答案:

答案 0 :(得分:3)

当调用此函数时(即从指令0x000083c8开始执行时),链接寄存器(LR)应该已经包含返回地址。快进到0x000083d8 puts 函数的返回结果根据ARM C调用约定(linklink)放在R0中。然后,返回地址从堆栈弹出到PC中 - 有效地结束了该函数的执行。这意味着0x000083e0处的说明不属于您的计划的一部分,您的检查应仅限于0x000083c80x000083dc的说明。

所以回答你的问题:

  1. 正确。
  2. 0x000083e0处的“指令”基本上是垃圾。您可能甚至没有对此内存的执行和/或访问权限,具体取决于您的ARM内核的具体情况(它是否有MMU等?)。因此,当试图检查该位置时,seg故障是合理的结果。
  3. 编辑:与下面的评论一致,0x000083e0的内容应解释为数据,而不是说明。

答案 1 :(得分:2)

0x000083e0处的四个字节不是垃圾。它是

的PC相对负载的一部分
0x000083d0 <+8>: ldr r0, [pc, #8]    ; 0x83e0 <main+24>

它在评论中也显示为; 0x83e0 <main+24>

此处出现问题,因为您需要将字符串的地址传递给puts,其地址可能在链接步骤中发生变化,编译器需要为此类进一步处理创建合适的代码。因此,字符串的地址在指令流中结束,但在任何执行上下文之外。