Gcc 为什么此函数序言使用多个指令来计算esp减少量?

Gcc 为什么此函数序言使用多个指令来计算esp减少量?,gcc,assembly,x86,Gcc,Assembly,X86,我已经查看了一些汇编代码转储,在主函数中有以下部分(找到和): <main+0>: push %ebp <main+1>: mov %esp, %ebp <main+3>: sub $0x8, %esp <main+6>: and $0xfffffff0, %esp <main+9>: mov $0x0, %eax <main+14>: add $0xf,

我已经查看了一些汇编代码转储,在主函数中有以下部分(找到和):

<main+0>:    push   %ebp
<main+1>:    mov    %esp, %ebp
<main+3>:    sub    $0x8, %esp
<main+6>:    and    $0xfffffff0, %esp
<main+9>:    mov    $0x0, %eax
<main+14>:   add    $0xf, %eax
<main+17>:   add    $0xf, %eax
<main+20>:   shr    $0x4, %eax
<main+23>:   shl    $0x4, %eax
<main+26>:   sub    %eax, %esp
:推送%ebp
:mov%esp,%ebp
:sub$0x8,%esp
:和$0xFFFFF0,%esp
:mov$0x0,%eax
:添加$0xf,%eax
:添加$0xf,%eax
:shr$0x4,%eax
:shl$0x4,%eax
:子%eax,%esp
你能解释一下(main+9)到(main+26)的用途吗?
为什么这样做是“低效的”?

那么你想在不做任何研究的情况下完整地走一遍?听起来合法

main+9:mov$0x0,%eax

加载带有十六进制0(=dec 0)的寄存器
eax

main+14:添加$0xf,%eax

十六进制F(=dec 15)添加到
eax
中的零

main+17:添加$0xf,%eax

十六进制F(=dec 15)再次添加到
eax
。这三个指令也可以由

movl $0x1e, %eax
但谁在数指令。。。无论如何,此时,
eax
包含十六进制1E,即12月30日

main+20:shr$0x4,%eax

eax
的内容向右移动四位

main+23:shl$0x4,%eax

将eax
eax
向右移回。为什么?因为这会清除最低的四位。现在eax包含十六进制10(=dec 16)

main+26:子%eax,%esp

esp
(堆栈指针)中减去
eax
。自

main+6:和$0xfffffff0,%esp


清除
esp
中的低位四位之前,根据ABI,新的
esp
将按16字节对齐。为什么不在
main+6
之后简单地使用esp呢?因为在x86上,堆栈从内存顶部向下增长。简单地屏蔽
esp
的低位可能会破坏局部变量。因此,减法将堆栈向下扩展到16字节边界。

这是gcc在2004年生成的代码吗?快乐的日子结束了!即使是最愚蠢的优化器也应该能够为main+9到main+26编写更好的代码。生成此程序集的输入(C代码?)是什么?编译器版本和标志是什么?同一序言可能重复。他们说这只发生在Windows和GCC3.X上,其中和
alloca
是genrated。谢谢大家的讨论。但是main+9到main+26不能由sub$0x10完成吗,%esp?@red-E:是的。这是非常非常可怕的代码,它使用的指令比需要的多得多。但它也是通用代码:类似的代码用于分配可变长度的堆栈缓冲区,因此编译器可以重用代码。