Assembly 程序集:局部变量的堆栈空间过大

Assembly 程序集:局部变量的堆栈空间过大,assembly,Assembly,我目前正在努力理解一些汇编代码,以便从中重构C代码。虽然我已经差不多完成了,但有一件关于局部变量的事情让我困惑 使用基本指针esp访问局部变量并减去其偏移量,例如,-0xc(%ebp)引用局部变量。要将其解释为C代码,我需要知道这些变量的大小(至少如果它们是数组)。可以通过计算其他变量偏移量的差异来实现这一点。如果存在局部变量-0xc(%ebp)和-0x8(%ebp),我们知道-0xc(%ebp)最有可能是4字节长。但是,如果在不可解析的数据库中没有其他访问任何局部变量的权限,那么-0x8(%e

我目前正在努力理解一些汇编代码,以便从中重构C代码。虽然我已经差不多完成了,但有一件关于局部变量的事情让我困惑

使用基本指针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)
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类型的值。