8

我使用 Visual C++ 2010 和 MASM 作为我的 x64 汇编程序。
这是我的 C++ 代码:

// include directive
#include "stdafx.h"
// functions
extern "C" int Asm();
extern "C" int (convention) sum(int x, int y) { return x + y; }
// main function
int main()
{
    // print asm
    printf("Asm returned %d.\n", Asm());
    // get char, return
    _getch();
    return EXIT_SUCCESS;
}

还有我的汇编代码:

; external functions
extern sum : proc
; code segment
.code
Asm proc
    ; create shadow space
    sub rsp, 20o
    ; setup parameters
    mov ecx, 10
    mov edx, 15
    ; call
    call sum
    ; clean-up shadow space
    add rsp, 20o
    ; return
    ret
Asm endp
end

我这样做的原因是我可以学习不同的调用约定。我将制定 sum 的调用约定 stdcall,并修改 asm 代码,使其以“stdcall”方式调用 sum。一旦我开始工作,我会做它,比如说,fastcall,然后以 asm 的“fastcall”方式调用它。

但是现在看看我的汇编代码。当我使用该代码时,无论 sum 是 stdcall、fastcall 还是 cdecl,它都会编译、执行并打印 25 作为我的 sum。

我的问题:如何以及为什么 __cdecl、__stdcall 和 __fastcall 都可以以完全相同的方式调用?

4

2 回答 2

12

问题是您正在为 x64 目标进行编译。来自MSDN

给定扩展的寄存器集,x64 只使用 __fastcall 调用约定和基于 RISC 的异常处理模型。__fastcall 模型对前四个参数使用寄存器,并使用堆栈帧来传递其他参数。

切换到针对 x86 目标进行编译,您应该能够看到各种调用约定在起作用。

于 2013-02-24T01:50:05.973 回答
5

据我所知,x64 仅使用 __fastcall 约定。__cdecl 和 stdcall 将被编译为 __fastcall。

于 2013-02-24T01:55:46.163 回答