我不明白为什么下面的行使用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
(完整代码)
我猜这段代码试图为函数调用推送3个参数。但是为什么不使用pushl
呢。这个代码的用途是什么?它是如何工作的?
Hans Passant回答正确。推/弹出操作码可以分解为两个微操作,分别进行内存移动和堆栈指针的递增/递减。如果堆栈指针(或任何指针)被更新,然后立即在下一个操作码中使用,则通常会发生执行暂停。通过堆栈指针访问各个内存位置(如您的示例中所示),将不会出现停滞,并且操作可以配对,从而允许它们同时执行。
任何超标量CPU类型都将尝试在一个周期内执行多个操作码,如果它们的结果/源彼此无关。编译器正在为您做一些加快执行速度的事情,而手工操作会相当费力。操作码可能比推送占用更多的空间,但它们的执行速度大约是推送的两倍——所有其他东西都是一样的。