我不明白为什么以下几行使用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
。这段代码的用法是什么?这是如何工作的?
答案 0 :(得分:3)
Hans Passant回答正确。推/弹操作码可以分解为两个微操作,它们执行存储器移动和堆栈指针的递增/递减。如果更新堆栈指针 - 或任何指针 - 然后立即在下一个操作码中使用,则通常会发生执行停顿。通过堆栈指针访问各个内存位置 - 如在您的示例中 - 将没有停顿并且操作可以配对,允许它们同时执行。
如果任何超标量CPU类型的结果/源与彼此无关,则它们将尝试在一个周期内执行多个操作码。编译器正在为您做一些事情来加速执行,这是相当费力的手工操作。操作码可能比推动占用更多的空间,但它们的执行速度大约是其两倍 - 所有其他事情都是相同的。