Assembly 程序集:局部变量的堆栈空间过大
我目前正在努力理解一些汇编代码,以便从中重构C代码。虽然我已经差不多完成了,但有一件关于局部变量的事情让我困惑 使用基本指针esp访问局部变量并减去其偏移量,例如,Assembly 程序集:局部变量的堆栈空间过大,assembly,Assembly,我目前正在努力理解一些汇编代码,以便从中重构C代码。虽然我已经差不多完成了,但有一件关于局部变量的事情让我困惑 使用基本指针esp访问局部变量并减去其偏移量,例如,-0xc(%ebp)引用局部变量。要将其解释为C代码,我需要知道这些变量的大小(至少如果它们是数组)。可以通过计算其他变量偏移量的差异来实现这一点。如果存在局部变量-0xc(%ebp)和-0x8(%ebp),我们知道-0xc(%ebp)最有可能是4字节长。但是,如果在不可解析的数据库中没有其他访问任何局部变量的权限,那么-0x8(%e
-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)
push%ebp
移动%esp,%ebp
局部变量的子$0x8,%esp//0x8=8字节
mov 0x8(%ebp),%eax//errormsg是一个函数参数
移动%eax,(%esp)
调用0x80485cc//perror(errormsg)
movl$0x1,(%esp)
调用0x804866c//退出(1)
这个函数显然不访问任何局部变量,因此我们可以怀疑没有局部变量。但是仍然有8个字节用于局部变量,不是吗
这并不是我见过的唯一一个例子,其中有空间分配给不需要的变量。我想我忽略了一些东西,但只要我这么做,我就不可能找出我需要编写C代码的所有变量的大小
有什么建议吗
提前谢谢 此处的指令
mov%eax,(%esp)
用于代替push
。因此,虽然没有使用任何局部变量,但保留的堆栈空间并没有被浪费。诚然,当函数只需要保留4个字节时,它似乎为局部变量保留了8个字节,但这可能是编译器使用的约定:始终以8个字节的块保留堆栈。保持堆栈qword对齐是有一定意义的。此处使用指令mov%eax,(%esp)
代替推送。因此,虽然没有使用任何局部变量,但保留的堆栈空间并没有被浪费。诚然,当函数只需要保留4个字节时,它似乎为局部变量保留了8个字节,但这可能是编译器使用的约定:始终以8个字节的块保留堆栈。保持堆栈qword对齐是有一定意义的。由于peror
是一个C函数(因此\uu cdecl
),第二个4字节部分(8字节alloc)被movl$0x1,(%esp)
用作退出的参数。通常,堆栈对齐是针对处理器字大小或SIMD访问对齐,它伴随着和ESP,0xFFFFFFC0
,其中peror
是一个C函数(因此\uu cdecl
),第二个4字节部分(8字节alloc)由movl$0x1,(%ESP)
,用作退出的参数。通常,堆栈对齐是与处理器字大小或SIMD访问对齐,这伴随着和ESP、0xFFFFC0
32位编译器将堆栈对齐为8。不这样做对存储double.32位编译器类型的值很不利。32位编译器将堆栈与8对齐。不这样做是在存储double类型的值。