繁体   English   中英

__cdecl调用约定在msvc x64上不起作用

[英]__cdecl calling convention not work on msvc x64

只是对__cdecl调用约定的测试。

这是一个cmake项目,只有一个源文件:

#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 2push 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
...

参数由寄存器edxecx传递,而不由堆栈传递。

那么,为什么即使我指定了__cdecl ,参数也不会在x64中通过堆栈传递,如果我想在x64环境中执行相同的操作,该怎么办。

x64有它自己的调用约定。

Microsoft文档__cdecl

在ARM和x64处理器上,可以接受__cdecl,但通常会被编译器忽略。 根据ARM和x64的约定,参数在可能的情况下在寄存器中传递,而后续参数在堆栈上传递。 在x64代码中,使用__cdecl覆盖/ Gv编译器选项,并使用默认的x64调用约定。

Microsoft docs x64 calling convention

默认情况下,x64应用程序二进制接口(ABI)使用四寄存器快速调用调用约定。 在调用堆栈上分配了空间作为影子存储,供被调用者保存这些寄存器。 函数调用的参数与用于这些参数的寄存器之间存在严格的一对一对应关系。 任何不适合8个字节或不是1、2、4或8个字节的参数都必须通过引用传递。

...

整数参数在寄存器RCX,RDX,R8和R9中传递

您可以通过int aint b使用ECX和EDX来查看它(因为它们是32位,而完整的RCX和RDX是64位)。

__stdcall__fastcall__thiscall也被忽略。 __vectorcall是可用的(/ Gv开关将其设置为默认值),并且是另一种调用寄存器的约定,但是与x64默认值相比,它可以在更多情况下使用寄存器,并且还有一些其他规则差异。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM