Просто тест для __cdecl
соглашения о вызовах.
Это проект cmake, имеющий только 1 исходный файл:
#include <stdio.h>
#define CALL_CONVENTION __cdecl
void CALL_CONVENTION f(int a, int b)
{
printf("%d, %d", a, b);
}
int main()
{
f(1, 2);
return 0;
}
Я использую set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /FA")
для вывода кода сборки.
и когда я строю с cmake -G "Visual Studio 15"
, это 32-битное приложение, и все в ожидании:
...
; Line 12
push ebp
mov ebp, esp
; Line 13
push 2 ; <------- argument 2
push 1 ; <------- argument 1
call _f ; <------- call function
add esp, 8
; Line 15
xor eax, eax
; Line 16
cmp ebp, esp
call __RTC_CheckEsp
pop ebp
ret 0
_main ENDP
...
Вы можете видеть, что аргументы передаются инструкциями push 2
и push 1
, это __cdecl
соглашение о вызовах.
Но если я использую cmake -G "Visual Studio 15 Win64"
для создания 64-битного приложения, аннотация __cdecl
не работает (аргументы не передаются в стеке):
...
; Line 12
$LN3:
push rdi
sub rsp, 32 ; 00000020H
mov rdi, rsp
mov ecx, 8
mov eax, -858993460 ; ccccccccH
rep stosd
; Line 13
mov edx, 2 ; <------ argument 2
mov ecx, 1 ; <------ argument 1
call f ; <------ call function
; Line 15
xor eax, eax
; Line 16
add rsp, 32 ; 00000020H
pop rdi
ret 0
main ENDP
...
аргументы передаются регистром edx
и ecx
, а не стеком.
Так почему аргументы не передаются по стеку в x64, даже если я указываю __cdecl
, и что мне делать, если я хочу делать то же самое в средах x64.