首页 > 解决方案 > 理解 GDB 中基本 C 程序中的 asm 指令

问题描述

在我尝试了解进程中的内存布局并学习汇编时,我在 Pi3 (ARM) 上编写了一个基本的 C 程序并使用 GDB 将其反汇编,但由于我是新手,因此我需要帮助理解它。

本质上,我试图理解并在程序集中发现变量存储的位置(BSS、DATA、TEXT 内存段),并且还理解并遵循堆栈帧。

我只显示了主要功能 - 调试屏幕上还有其他部分,所以让我知道它们是否也有帮助!

我了解各个指令在很大程度上是做什么的,但我想知道的是:

  1. 前 3 行与堆栈指针有关,这是为 main 函数设置堆栈帧吗?

  2. 在 x0x10414 它使用年龄的值,这是局部变量作为主函数框架的一部分弹出到堆栈中的地方吗?

  3. 在 x0x1041c 处,我假设的返回值是否也作为帧的一部分被推入堆栈?

  4. 函数末尾刷新的堆栈在哪里?

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   

标签: cassemblyarm

解决方案


  1. 是的你是对的。寄存器r11用作帧指针。此帧指针用作对局部变量在堆栈中存储位置的引用。请注意,必须保留来自调用者的原始帧指针(以便稍后保存和恢复)。
  2. 几乎。它在一行之后发生,它将它存储在堆栈中的 [r11 - 8] 处。请记住,这r11是帧指针,一切都是相对的。
  3. 它不会被压入堆栈。它只是在 register 中返回r0。在许多平台上使用通用寄存器很常见。然后堆栈不需要用于简单和普通的返回值(比如你的整数)。我想这是出于性能原因,因为寄存器比内存访问快。
  4. 不知道你说的脸红是什么意思。这里发生的是函数按照它喜欢的方式进行设置,然后恢复这些更改。堆栈的内容可能仍包含函数使用的值。只是指针被重置到其原始位置。首先在函数的开头,原始帧指针 ( r11) 被保存/推送到堆栈上。然后堆栈指针的值成为新的帧指针。在函数结束时,堆栈指针返回到原来的位置(通过用 覆盖它r11),最后r11通过将其从堆栈中弹出来恢复自身。

推荐阅读