为什么它使用MOVL而不是推?为什么它使用MOVL而不是推?(why does it use the

2019-05-12 01:57发布

注意下面的代码:

#include <stdio.h>
void a(int a, int b, int c)
{
    char buffer1[5];
    char buffer2[10];
}

int main()
{
    a(1,2,3); 
}

之后 :

gcc -S a.c

该命令显示在我们的汇编源代码。

现在我们可以在主函数中看到的,我们从来不使用“推”命令,将一个函数的参数推入堆栈。 它使用“MOVEL”,而不是说

main:
 pushl %ebp
 movl %esp, %ebp
 andl $-16, %esp
 subl $16, %esp
 movl $3, 8(%esp)
 movl $2, 4(%esp)
 movl $1, (%esp)
 call a
 leave

为什么会发生? 什么是他们之间的区别?

Answer 1:

下面是gcc的手册有说些什么:

-mpush-args
-mno-push-args
    Use PUSH operations to store outgoing parameters. This method is shorter and usually
    equally fast as method using SUB/MOV operations and is enabled by default. 
    In some cases disabling it may improve performance because of improved scheduling
    and reduced dependencies.

 -maccumulate-outgoing-args
    If enabled, the maximum amount of space required for outgoing arguments will be
    computed in the function prologue. This is faster on most modern CPUs because of
    reduced dependencies, improved scheduling and reduced stack usage when preferred
    stack boundary is not equal to 2. The drawback is a notable increase in code size.
    This switch implies -mno-push-args. 

显然-maccumulate-outgoing-args是默认启用的,覆盖-mpush-args 。 用显式编译-mno-accumulate-outgoing-args不会恢复到PUSH方法,在这里。



Answer 2:

该代码只是直接从(更新)栈指针(ESP)偏移的位置(3 1,2,)把常数。 编译器选择与相同的结果做手工“推”。

“推”两组数据并更新堆栈指针。 在这种情况下,编译器被减少到堆栈指针的仅一个更新(相对于3)。 一个有趣的实验是将尝试改变功能的“一”,采取只有一个参数,看看指令格局的变化。



Answer 3:

的gcc做各种优化的,包括选择基于特定CPU的执行速度被优化的指令。 你会发现,之类的东西x *= n通常由SHL的组合取代,添加和/或SUB,特别是当n是一个常数; 而MUL仅用于当SHL-ADD-SUB的组合的平均运行时间(和高速缓存/等。脚印)将超过MUL的,或n不是常数(因此使用循环与SHL-附加子将前来昂贵)。

在函数参数的情况下:MOV可以通过硬件并行,而PUSH不能。 (第二推动必须等待第一PUSH到因为ESP寄存器的更新的完成)。在的函数的参数的情况下,可以的MOV并行运行。



Answer 4:

这是在OS X上的任何机会? 我读的地方,它需要在16字节边界对齐堆栈指针。 这可能可以解释这种代码生成的。

我发现的文章: http://blogs.embarcadero.com/eboling/2009/05/20/5607



Answer 5:

奔腾指令集不具有用于推动一个恒定压入堆栈的指令。 因此,使用push将是缓慢:该计划将必须把不断在寄存器和推寄存器:

...
movl $1, %eax
pushl %eax
...

所以编译器检测到使用movl更快。 我想你可以尝试调用你的函数变量而不是常量:

int x;
scanf("%d", &x); // make sure x is not a constant
a(x, x, x);


文章来源: why does it use the movl instead of push?
标签: c assembly stack