C函数调用约定:为什么要使用movl而不是pushl?

时间:2014-04-26 10:32:02

标签: assembly x86 32-bit disassembly gas

我不明白为什么以下几行使用movl将数据推送到堆栈指针下面是由GCC产生的。

movl    -4(%ebp), %eax      # -4(%ebp) <- local variable 1
movl    8(%ebp), %edx       # 8(%ebp)  <- first parameter
movl    %edx, 8(%esp)       # ??? WHY NOT:   pushl %edx
movl    %eax, 4(%esp)       # ??? WHY NOT:   pushl %eax
movl    -8(%ebp), %eax      # ??? WHY NOT:   pushl -8(%ebp)
movl    %eax, (%esp)
call    athena
movl    %eax, f

(full code)

我猜这段代码试图为函数调用推送3个参数。但为什么不使用pushl。这段代码的用法是什么?这是如何工作的?

1 个答案:

答案 0 :(得分:3)

Hans Passant回答正确。推/弹操作码可以分解为两个微操作,它们执行存储器移动和堆栈指针的递增/递减。如果更新堆栈指针 - 或任何指针 - 然后立即在下一个操作码中使用,则通常会发生执行停顿。通过堆栈指针访问各个内存位置 - 如在您的示例中 - 将没有停顿并且操作可以配对,允许它们同时执行。

如果任何超标量CPU类型的结果/源与彼此无关,则它们将尝试在一个周期内执行多个操作码。编译器正在为您做一些事情来加速执行,这是相当费力的手工操作。操作码可能比推动占用更多的空间,但它们的执行速度大约是其两倍 - 所有其他事情都是相同的。