【问题标题】:Debugging C program (int declaration)调试 C 程序(int 声明)
【发布时间】:2013-10-13 03:39:31
【问题描述】:

我仍在学习汇编和 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

提前致谢!

【问题讨论】:

  • 只是出于好奇,您使用的是 gcc 吗?如果是,哪个版本?
  • gcc 版本 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1)

标签: c debugging assembly stack


【解决方案1】:
   0x080483f9 <+3>:     sub    $0x10,%esp

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

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

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

【讨论】:

  • 0x10 是十进制的16。那么为什么sub指令意味着栈帧的大小是4字节呢?
  • @us2012:你完全正确,我忽略了这一点。我只是休息一下;)
  • 好多了,+1 :) 如果您对 为什么 堆栈帧似乎比要求的更大有一个解释,那就太棒了。
  • 所以 movl 将 0xa (10d) 移动到 ebp (main) 的偏移量 -0x4。非常感谢:D
  • @us2012 你在这里 :)
猜你喜欢
  • 2017-08-10
  • 1970-01-01
  • 2019-02-06
  • 2010-11-20
  • 1970-01-01
  • 1970-01-01
  • 2014-01-31
  • 2020-05-30
  • 1970-01-01
相关资源
最近更新 更多