I couldn't find any documentation on the Windows RT on ARM calling convention used by Visual Studio C++. Is Microsoft using ARM's AAPCS?
If Microsoft is using the AAPCS/EABI for Windows RT on ARM, is it also using ARM's C++ ABI (which is derived from the Itanium C++ ABI)? Maybe even the ARM exception handling ABI?
Does the calling convention used by Windows RT on ARM differ from that used by other (embedded) ARM Windows variants?
Is there a reliable way to detect Windows RT on ARM through predefined compiler macros?
Update: Added the question regarding the C++ ABI.
Unlike Windows CE (which uses original APCS aka Old ABI), Windows RT on ARM uses EABI. More specifically, the variant which uses floating-point registers to pass floating-point data and 8-byte stack/argument alignment.
If I take the following function:
int g(float x) {
return x;
}
and compile it with VS2012's ARM compiler, I get the following assembly:
|g| PROC
vcvt.s32.f32 s0,s0
vmov r0,s0
bx lr
ENDP ; |g|
You can see that it's using S0
and not R0
for the argument.
The one from VS2008 (which can be used to target older Windows CE versions) produces this:
str lr, [sp,#-4]!
ldr r3, =__imp___stoi
ldr r3, [r3]
mov lr, pc
bx r3
ldr pc, [sp],#4
This code is calling a helper function to perform the conversion.
The Windows CE compiler shipped with Windows Compact 7 supports both the old calling convention (called "cdecl" by MS) and EABI. See What's New in Platform Builder 7.
EDIT: just now noticed you added a question about C++. Microsoft does not use Itanium-style C++ ABI, since their implementation predates it. You can read about Microsoft's implementation in my OpenRCE articles (1, 2) and the follow-up Recon presentation. See also the original description from the designer Jan Gray: PDF.
I can only answer the 2nd question.
Does the calling convention used by Windows RT on ARM differ from that used by other (embedded) ARM Windows variants?
There are actually three concept that should be understood. One is the ARM Procedure Call Standard, another is the Language ABI and a third is the system call convention. Briefly, the ARM Procedure Call Standard describes register use in a prologue/epilogue. The Language ABI describe how language variables are passed. Ie, a double, a long long, the this pointer, dynamic_cast<>
, etc. The first is needed to interface assembler with the compiler, the 2nd is needed for compiler interoperability. The 3rd is how OS calls are made.
The apcs.txt document helps to understand some of the ARM variants. There are 16 variants based on four different choices.
So while there are sixteen theoretical variations, for modern systems using an MMU there are only two. The Debian ARM hard float wiki gives information that some Linux/gcc distributions have under went. I would guess that Window RT is using hard float as they would not want to pay a performance price to support outdated hardware. Finally, it is hard to think that shared library or DLL support wouldn't be present in Window RT. So the ARM Procedure Call Standard seems to be identical to a Linux hard float ABI.
The AAPCS defines how languages are meant to map high level function/methods to low level details. Name mangling ensures that symbols has canonical names so that cross tool linking is possible. AAPCS tools should theoretically inter-operate, but issues may appear with support libraries and other system level interfaces.
The Embedded ARM wiki gives some information on this standard. An OS using an MMU will use some calls to transition from user mode to system mode. Generally, these are library only features and are not part of the compiler. However, you can certainly find some ARM systems that use the OABI convention. As Microsoft is late the ARM game, they will either use the EABI or invented something new. For instance, calling malloc()
with a gcc linux hard-float compiler will not work as the system calls will be completely different. Generally you will have to compile with -nostdlib
and invent your own C-library.
I have googled a little bit to find specifics on Visual C++.
So to answer your 2nd question, there are a lot of compilers/systems that will generate similar prologue/epilogue. If the Visual C++ uses the AAPCS, then it can inter-operate with other AAPCS compilers. You may have to create custom libraries to get another compiler to call Windows RT system calls. The other questions should be answered in a manual.
Edit: GCC's ARM -mabi selects the ABI. aapcs-linux is AAPCS/EABI, apcs-gnu is the OABI defining prologue/epilogue and argument mappings. Compiler configuration select the target OS and instruction/back-end/CPU type; so we have compilers with different names, like arm-linux-eabi-gcc
, arm-linux-gnueabi-gcc`, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With