为什么MS在x86上的快速调用不使用EAX作为第一个参数?

时间:2014-02-04 18:23:37

标签: x86 cpu-registers fastcall

根据维基百科:" Microsoft或GCC __fastcall约定(又名__msfastcall)传递适合ECX和EDX的前两个参数(从左到右评估)。剩下的参数从右到左被压入堆栈。"

为什么他们决定不使用arx0,arg1,arg2的EAX,ECX,EDX?如果他们要将参数推入寄存器,为什么要停在2?我知道Borland的所有DOES都这么做,所以微软选择不使用EAX只是为了与众不同吗?

1 个答案:

答案 0 :(得分:-3)

由于设置了x86命令的限制,没有执行CALL立即
命令,有CALL IP.offset,
是相对的。当然,编译器编写者希望保留具有绝对偏移量的东西,并且处理器制造商可能会要求这样做,因此我们有以下"妥协":
MOV eax,absolute_address(标签)
CALL eax
这将等于
CALL absolute_address(label)
这种调用方法需要1个临时寄存器,仅用于调用,可以很容易地重复使用,而EAX是用于此目的的最佳选择。
这些注意事项的结果很有用,您可以在asm代码中使用它。基准测试表明,分支预测器至少可以部分地与这些代码一起正常工作。 另一种可能性,但是很少见,就是当你必须重置标志以避免在调用已经在顶级缓存中的过程时的依赖性惩罚或部分寄存器停顿时。例如,如果在子例程的最开始使用mov ah,1之类的东西,就会发生这种情况。为避免这种情况,请使用EAX作为临时寄存器并放入 XOR eax,eax
在CALL之前。在极少数情况下,它实际上可以节省几个时钟周期。但这样做的实际好处与使用它进行参数传递是值得怀疑的,原因可能如上所述。