我目前正在尝试很好地理解一些汇编代码,以便从中重构C代码。虽然我已经接近完成了,但有一点关于局部变量让我感到困惑。
使用Base Pointer esp访问局部变量并减去它们的偏移量,例如: -0xc(%ebp)
引用局部变量。要将其解释为C代码,我需要知道这些变量的大小(至少如果它们是数组)。可以通过计算与其他变量的偏移的差异来做到这一点。如果存在局部变量-0xc(%ebp)
和-0x8(%ebp)
,我们知道-0xc(%ebp)
最有可能是4个字节长。但是,如果在反汇编中没有其他任何本地变量的访问权限,那么-0x8(%ebp)
呢?我们可以建议它的大小必须是8个字节吗?我不这么认为......
我的问题是:编译器似乎为局部变量留出了比需要更多的空间。让我告诉你这个简单的例子:一个错误函数,用gdb反汇编。
push %ebp
mov %esp,%ebp
sub $0x8,%esp // 0x8 = 8 byte for local variables
mov 0x8(%ebp),%eax // errormsg is a function argument
mov %eax,(%esp)
call 0x80485cc <perror@plt> // perror(errormsg)
movl $0x1,(%esp)
call 0x804866c <exit@plt> // exit(1)
这个函数显然不会访问任何局部变量,所以我们可以怀疑没有。但仍有8个字节留给局部变量,不存在吗?
这不是我见过的唯一一个为不需要的变量分配空间的例子。我想我忽略了一些东西,但是只要我这样做,我就无法找到编写C代码所需的所有变量的大小。
有什么建议吗?
提前致谢!
答案 0 :(得分:3)
此处的mov %eax,(%esp)
指令用于代替push
。因此,虽然没有使用任何局部变量,但它不像浪费的保留堆栈空间。当然,当它只需要保留4时,看起来该函数为局部变量保留8个字节,但也许这是编译器使用的约定:始终以8个字节的块保留堆栈。保持堆栈qword对齐有一定的意义。