2013-02-05 72 views
8

根据Wikipedia,英特尔ABI允许使用EAX,ECXEDX而不将它们保留在函数中。
我不确定“Intel ABI”是什么意思。这是否意味着所有针对英特尔CPU的编译器都强制执行/遵循这个规定?我在写一个将从C代码调用的汇编函数。我可以为所有编译器假设这一点吗? (目前我只针对x86哪些寄存器在函数中可以安全使用(x86)

回答

6

英特尔ABI只是由英特尔设立的通话协议。

一般而言,参数的传递和寄存器函数调用期间保存或丢弃由函数的调用约定定义:

http://en.wikipedia.org/wiki/Calling_convention

尤其对于__cdecl,__stdcall和__fastcall你应该期望EAX,ECX和EDX被丢弃,并且你的函数应该保留其他的寄存器并且在EAX(或者EDX:EAX中返回64位)返回。

如果您不知道应该使用的调用约定是什么,那么您不应该在汇编中编写代码,因为搞乱调用约定会导致应用程序中的可利用的错误。

在C中,默认调用约定通常是__cdecl,对于Windows导出的API,通常是__stdcall。

+0

我知道我需要使用的调用约定,并且只要参数和堆栈清理的顺序知道它的含义。我不知道寄存器。你知道哪些编译器遵循这个ABI吗? MSVC/GCC? – baruch

+0

@baruch至少对于MSVC来说,调用约定是在函数原型中指定的。编译器查看这个并做正确的事情。例如,WSARecv的def像这样开始:int WSAAPI WSARecv。 WSAAPI解决了(通过几个#defines)到__stdcall。 –

+0

@MarcSherman我知道调用约定,但是调用约定的寄存器保留部分? – baruch

1

它是英特尔应用程序二进制接口,一组规则指示什么寄存器可用而不保存,如何将参数压入堆栈,主叫方或被叫方是否清除堆栈帧等。

如果你知道规则正在遵循,那很好。我倾向于保存一切以防万一(除了那些我用来返回信息的东西)。

但并非所有编译器都强制执行,除非编译器明确说明,否则您不应该这样想。

相关问题