Windows RT在ARM上的本机代码调用约定是什么?
What is the Windows RT on ARM native code calling convention?
我找不到任何关于Visual Studio c++使用的Windows RT on ARM调用约定的文档。微软是否在使用ARM的AAPCS?
如果微软在ARM上使用Windows RT的AAPCS/EABI,它是否也使用ARM的c++ ABI(派生自Itanium c++ ABI)?甚至ARM异常处理ABI?
Windows RT在ARM上使用的调用约定与其他(嵌入式)ARM Windows变体使用的调用约定不同吗?
是否有一个可靠的方法来检测Windows RT在ARM上通过预定义的编译器宏?
更新:增加了关于c++ ABI的问题。
与Windows CE(使用原始APCS即旧ABI)不同,ARM上的Windows RT使用EABI。更具体地说,使用浮点寄存器传递浮点数据和8字节堆栈/参数对齐的变体。
如果我取下面的函数:
int g(float x) {
return x;
}
并使用VS2012的ARM编译器编译,我得到以下程序集:
|g| PROC
vcvt.s32.f32 s0,s0
vmov r0,s0
bx lr
ENDP ; |g|
您可以看到它使用S0
而不是R0
作为参数。
来自VS2008的(可用于针对旧的Windows CE版本)产生如下:
str lr, [sp,#-4]!
ldr r3, =__imp___stoi
ldr r3, [r3]
mov lr, pc
bx r3
ldr pc, [sp],#4
这段代码调用了一个辅助函数来执行转换。
Windows Compact 7附带的Windows CE编译器既支持旧的调用约定(MS称为"cdecl"),也支持EABI。参见Platform Builder 7的新功能。
EDIT:刚才注意到你加了一个关于c++的问题。微软没有使用itanium风格的c++ ABI,因为他们的实现早于itanium。您可以在我的OpenRCE文章(1、2)和后续的Recon演示中了解微软的实现。参见设计师Jan Gray的原始描述:PDF.
我只能回答2和的问题。
Windows RT在ARM上使用的调用约定与其他(嵌入式)ARM Windows变体使用的调用约定不同吗?
实际上有三个概念应该被理解。一个是ARM过程调用标准,另一个是语言ABI,第三个是系统调用约定。简单地说,ARM过程调用标准描述了寄存器在序言/尾声中的使用。语言ABI描述如何传递语言变量。例如,一个double,一个long long, this指针,dynamic_cast<>
等等。第一个是汇编器与编译器之间的接口,2和是编译器互操作性所需要的。3和是操作系统调用的方式。
ARM过程调用标准
apcs.txt文档有助于理解一些ARM变体。基于四种不同的选择,有16种变体。
- 32位vs 26位PC -所有2000年以后的版本将使用32位。
- 堆栈限制检查-可能被重新表述为MMU或无MMU。
- 浮点-大约在2005年之后在大多数CPU上支持。
- 可重入vs不可重入—纯软件选择;共享库吗?
因此,虽然理论上有16种变化,但对于使用MMU的现代系统来说,只有两种。Debian ARM硬浮动wiki提供了一些Linux/gcc发行版的信息。我猜windows RT正在使用硬浮点,因为他们不想为支持过时的硬件而付出性能代价。最后,很难想象在windows rt中不存在共享库或DLL支持。因此ARM过程调用标准似乎与Linux硬浮点数 ABI相同。
C/c++的ABI
AAPCS定义了语言如何将高级函数/方法映射到低级细节。名称混淆确保符号具有规范的名称,以便可以进行跨工具链接。AAPCS工具理论上应该可以互操作,但是支持库和其他系统级接口可能会出现问题。
OABI/EABI
嵌入式ARM wiki给出了这个标准的一些信息。使用MMU的操作系统将使用一些调用从用户模式转换到系统模式。一般来说,这些都是库独有的特性,而不是编译器的一部分。但是,您肯定可以找到一些使用OABI约定的ARM系统。由于微软在ARM游戏中落后,他们要么使用EABI,要么发明一些新的东西。例如,使用gcc linux hard-float编译器调用malloc()
将无法工作,因为系统调用将完全不同。一般来说,你必须使用-nostdlib
进行编译,并创建自己的 c库。
我在谷歌上搜索了一些关于Visual c++的细节。
- MSDN在ARM Windows CE
- SO ARM调用约定
所以回答你的2和的问题,有很多编译器/系统会生成类似的序言/尾声。如果Visual c++使用AAPCS,那么它可以与其他AAPCS编译器互操作。您可能必须创建自定义库,以使另一个编译器调用Windows RT系统调用。其他问题应该在手册中回答。
Edit: GCC的ARM -mabi选择ABI。AAPCS -linux是AAPCS/EABI, apcs-gnu是OABI定义序言/尾声和参数映射。编译器配置选择目标操作系统和指令/后端/CPU类型;所以我们有不同名称的编译器,如arm-linux-eabi-gcc
, arm-linux-gnueabi-gcc '等。
- 为什么在 x64 中忽略__stdcall调用约定?
- 窗口调用约定
- 我应该提到纯虚函数中的调用约定吗?
- 如何使用gcc指定stdcall调用约定
- Clang:x86 FPU调用约定
- 该标准是否说明了例外和不同调用约定的共存
- Clang++的InterlockedExchange的32位调用约定错误,但MSVC可以
- std::sort & comp - 调用约定?
- 如何为类 /块 /范围选择C 调用约定
- DLL 的"good"调用约定是什么?
- 结构中重载运算符的调用约定
- 'ShowSUM':__declspec(dllexport)不能应用于具有__clrcall调用约定的函数
- x86-64 调用约定中的返回值
- 内联功能和调用约定
- 正在直接显示筛选器中调用约定
- 何时使用`__fastcall`调用约定
- 为C++结构定义显式析构函数如何影响调用约定
- 由于使用 MFC 时"__cdecl"和"__thiscall"调用约定不匹配而导致的链接器错误?
- Microsoft Visual C++是否未使用带有浮点的C/C++调用约定
- 在Visual Studio中调用约定