c - 调试 C 程序(int 声明)

标签 c debugging assembly stack

我仍在学习汇编和 C,但现在,我正在尝试了解编译器的工作原理。我这里有一个简单的代码:

int sub()
{
  return 0xBEEF;
}
main()
{
  int a=10;
  sub();
}

现在我已经知道 CPU 是如何工作的,跳转到框架和子程序等。 我不明白的是程序在哪里“存储”它们的局部变量。在这种情况下是在主要框架中吗?

这是调试器的主框架:

   0x080483f6 <+0>:     push   %ebp
   0x080483f7 <+1>:     mov    %esp,%ebp
   0x080483f9 <+3>:     sub    $0x10,%esp
=> 0x080483fc <+6>:     movl   $0xa,-0x4(%ebp)
   0x08048403 <+13>:    call   0x80483ec <sub>
   0x08048408 <+18>:    leave  
   0x08048409 <+19>:    ret 

我有“int a=10;”一个断点,这就是偏移量 6 具有该箭头的原因。 所以,main 的功能开始像其他人一样插入 ebp bla bla bla,然后我不明白这一点:

   0x080483f9 <+3>:     sub    $0x10,%esp
=> 0x080483fc <+6>:     movl   $0xa,-0x4(%ebp)

为什么在esp中做sub?堆栈指针的偏移量为-0x4 的变量'a' 是否在堆栈中?

只是为了澄清这里的想法:D

提前致谢!

最佳答案

   0x080483f9 <+3>:     sub    $0x10,%esp

你会在每个函数中找到这样的指令。它的目的是创建一个适当大小的栈帧,以便函数可以存储它的局部变量(记住栈是向后增长的!)。
在这种情况下,栈帧有点太大了。这是因为 gcc(从 2.96 开始)默认将堆栈帧填充到 16 字节边界,以解决 SSEx 指令,这些指令需要将打包的 128 位 vector 对齐到 16 字节。 (引用 here)。

=> 0x080483fc <+6>:     movl   $0xa,-0x4(%ebp)

此行将 a 初始化为正确的值 (0xa = 10d)。局部变量总是用相对于 ebp 的偏移量引用,这标志着堆栈帧的开始(因此包含在 ebp 和 esp 之间)。

关于c - 调试 C 程序(int 声明),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19210032/

相关文章:

c - 如何保证数组内指针比较的有效性?

C malloc + free 不断增加内存占用

javascript - 页面刷新前的断点?

assembly - 在汇编宏中创建循环 - IAR ARM

c - C 中的指针问题

c - 如何知道C中单个程序分配的内存的完整大小?

linux - 无法在 centos7 上为调试内核设置​​故障转储

c# - "Indicates the start of a managed heap garbage collection"到底是什么意思,是不是不好?

ios - 如何将 Xcode 4.2 的 iOS 反汇编从 Thumb 切换到 ARM?

gcc - 在标量矩阵加法中使用 vaddss 代替 adds 有什么好处?