cdecl&stdcall

cdecl

cdecl的caller才回去清理stack。生成的exe会比较大。

参数传递方式是从右到左,caller有责任pop stack

规范上,Underscore character (_) is prefixed to names, except when __cdecl functions that use C linkage are exported.

放在函数名之前来修饰,默认是C语言的调用规范,如果加了其他的调用规范参数需要在函数名之前添加修饰。

其他的调用规范为/ /Gv (vectorcall), /Gz (stdcall), or /Gr (fastcall) 

The /Gd compiler option forces the __cdecl calling convention.

在arm 或者是x64的cpu上,_cdecl能接受,但是会被忽略。

因为在arm或者是x64上会尽可能的使用寄存器来传参,剩余的会使用stack

x64的代码中,使用__cdecl来重载/Gv 编译器选项,然后会默认使用x64默认的规范

使用:

// Example of the __cdecl keyword on function  
int __cdecl system(const char *);  
// Example of the __cdecl keyword on function pointer  
typedef BOOL (__cdecl *funcname_ptr)(void * arg1, const char * arg2, DWORD flags, ...);

stdcall

The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl. Functions that use this calling convention require a function prototype.

入栈是从右到左。

传值立即数,除非是指针引用

callee被调用者自己弹栈stack

命名修饰上

An underscore (_) is prefixed to the name. The name is followed by the at sign (@) followed by the number of bytes (in decimal) in the argument list. Therefore, the function declared as int func( int a, double b ) is decorated as follows: _func@12

函数名之前有_func之后跟@ ,之后跟参数的字节数

例如

int  func(int a,double b)的就是_func@12

/Gz编译器指定__stdcall约定。

同样arm和x64会被接收但是会被忽略,传值优先寄存器之后stack

非静态调用下,不用再dll ,so那一层来添加修饰__stdcall。

只用在使用的一层添加就好了,比如头文件声明部分。

例如

// Example of the __stdcall keyword

#define WINAPI __stdcall

// Example of the __stdcall keyword on function pointer

typedef BOOL (__stdcall *funcname_ptr)(void * arg1, const char * arg2, DWORD flags, ...);

__fastcall

x86下,尽可能使用fastcalll

The first two DWORD or smaller arguments that are found in the argument list from left to right are passed in ECX and EDX registers; all other arguments are passed on the stack from right to left.

在参数表从左到右中找到两个dword或者小的参数,会传入ECX和EDX寄存器,

所有其他的会被传入stack从右到左。

依然是被调用的函数自己pop栈

修饰是依照上边的例子func函数的修饰后是@func@12

用/Gr来制定编译器选项,

The __fastcall keyword is accepted and ignored by the compilers that target ARM and x64 architectures; on an x64 chip, by convention, the first four arguments are passed in registers when possible, and additional arguments are passed on the stack. For more information, see Overview of x64 Calling Conventions. On an ARM chip, up to four integer arguments and eight floating-point arguments may be passed in registers, and additional arguments are passed on the stack.

例如


// Example of the __fastcall keyword  
#define FASTCALL    __fastcall  


void FASTCALL DeleteAggrWrapper(void* pWrapper);  
// Example of the __ fastcall keyword on function pointer  
typedef BOOL (__fastcall *funcname_ptr)(void * arg1, const char * arg2, DWORD flags, ...);

REFER:

https://docs.microsoft.com/en-us/cpp/cpp/results-of-calling-example


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
__cdecl 和 __stdcall 都是 C/C++ 函数调用的约定,用于指明函数参数的传递方式和堆栈的清理方式。它们的主要区别在于参数传递的顺序、堆栈的清理方式和函数调用的速度。 __cdecl 是默认的调用约定,参数从右往左依次压入堆栈,由调用方清理堆栈。这意味着参数的顺序是反向的,而且每次函数调用后都需要调用方清理堆栈。例如: ```c++ void __cdecl myFunction(int a, int b, int c) { // function body } int main() { myFunction(1, 2, 3); return 0; } ``` 在上面的例子中,参数 3 会先被压入堆栈,然后是参数 2 和 1,最后调用函数 myFunction。函数 myFunction 执行完毕后,调用方负责清理堆栈。 __stdcall 是一种常用的调用约定,参数从右往左依次压入堆栈,由被调用方清理堆栈。这意味着参数的顺序是反向的,但被调用方负责清理堆栈。例如: ```c++ void __stdcall myFunction(int a, int b, int c) { // function body } int main() { myFunction(1, 2, 3); return 0; } ``` 在上面的例子中,参数 3 会先被压入堆栈,然后是参数 2 和 1,最后调用函数 myFunction。函数 myFunction 执行完毕后,被调用方负责清理堆栈。 总的来说,__stdcall 比 __cdecl 调用约定速度更快,因为不需要调用方清理堆栈。但是,__stdcall 只适用于固定数量的参数,而且参数的类型必须是已知的,因为被调用方需要知道清理堆栈的大小。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值