在我试图理解进程中的内存布局并学习汇编的过程中,我在Pi3(ARM)上编写了一个基本的C程序,并使用GDB将其反汇编,但由于我是新手,我需要帮助理解它。
从本质上讲,我试图理解和发现程序集中存储变量的位置(BSS、数据、文本内存段),并理解并遵循堆栈帧。
我只显示了主要功能 - 调试屏幕上还有其他部分,所以让我知道它们是否也会有所帮助!
我了解各个说明在大多数情况下都在做什么,但我想知道的是:
-
前 3 行与堆栈指针有关,这是为 main 函数设置堆栈帧吗?
-
在 x0x10414 处,它使用的是年龄值,这是局部变量作为主函数帧的一部分弹出到堆栈上的地方吗?
-
在 x0x1041c 时,我假设的返回值也作为帧的一部分被推到堆栈上吗?
-
函数结束时的堆栈刷新在哪里?
int main () {
int age = 30;
int salary;
return 0;
}
0x10408 <main> push {r11} ; (str r11, [sp, #-4]!)
x0x1040c <main+4> add r11, sp, #0
x0x10410 <main+8> sub sp, sp, #12
x0x10414 <main+12> mov r3, #30
x0x10418 <main+16> str r3, [r11, #-8]
x0x1041c <main+20> mov r3, #0
x0x10420 <main+24> mov r0, r3
x0x10424 <main+28> add sp, r11, #0
x0x10428 <main+32> pop {r11} ; (ldr r11, [sp], #4)
x0x1042c <main+36> bx lr
- 是的,你是对的。寄存器
r11
用作帧指针。此帧指针用作局部变量在堆栈上的存储位置的参考。请注意,必须保留来自调用方的原始帧指针(以便稍后保存和还原)。 - 几乎。它发生在一行之后,它将其存储在 [r11 - 8] 的堆栈上。 请记住,
r11
是帧指针,一切都是相对的。 - 它不会推送到堆栈上。它只是在寄存器
r0
中返回。 在许多平台上,使用通用寄存器是很常见的。然后,堆栈不需要用于简单和普通的返回值(如整数)。我想这是出于性能原因,因为寄存器比内存访问更快。 - 我不知道你说的脸红是什么意思。这里发生的事情是,该函数按照它喜欢的方式设置内容,然后还原这些更改。堆栈的内容可能仍包含函数使用的值。只是指针被重置到其原始位置。首先在函数的开头,原始帧指针(
r11
)被保存/推送到堆栈上。 然后,堆栈指针的值将成为新的帧指针。 在函数结束时,堆栈指针返回到它原来的位置(通过用r11
覆盖它),最后r11
通过将其从堆栈中弹出来恢复自身。