c++之于80X86汇编之stdcall,cdecl调用

stdcall:windows API调用方式,即WINAPI。

cdecl:c语言默认调用方式。

问题的由来。不同的调用方式,包括其它调用方式,fastcall,thiscall等等,主要是为了解决函数调用中,参数的传递问题。stdcall和cdecl调用都是通过栈来传递参数。调用之前先将参数入栈,再调用函数,调用后再清理栈。由此就有了不同的调用方式约定,这些调用方式决定了参数的传递方式及清理栈的负责方(调用方或被调用方)。

具体表现。在asm层面,两者表现为ESP指针的调整对象为调用方或被调用方。stdcall,ESP由被调用方,即函数本身来调整栈顶指针(ESP).;cdecl,ESP由调用方调整ESP。最终使执行下一条语句之前名ESP指针恢复到原来的值。在asm代码层面表现为:stdcall 调用 方式最后ret 指令为 ret x; 意义为函数调用结束,并且执行add esp,x。而cdecl调用方式,只是最后简单执行ret指令,因为由调用方来平衡栈。

那么为什么非要使调用后的ESP与调用之前一致呢?其中最重要的一点就是节省内存空间。若是不恢复ESP,则会一直增大,最后会使栈本身很大,没有内存可分配。

例:

c/c++代码:

int _stdcall add_stdcall(int m,int n)
{
    return m+n;
}
int _cdecl add_cdecl(int m,int n)
{
    return m+n;
}

等效的80x86 ASM代码:

add_stdcall proc
	push ebp
	mov ebp,esp
	
	mov eax,DWORD PTR [ebp+8]
	add eax,DWORD PTR [ebp+12]
	
	mov esp,ebp
	pop ebp
	ret 8
add_stdcall endp

add_cdecl proc
	push ebp
	mov ebp,esp
	
	mov eax,DWORD PTR [ebp+8]
	add eax,DWORD PTR [ebp+12]
	
	mov esp,ebp
	pop ebp
	ret
add_cdecl endp    

调用方式如下:

;szfmt db 'result=%u',13,10,0 

;stdcall
push 100
push 200
call add_stdcall

push eax
push offset szfmt
call crt_printf
add esp,8
;cdecl
push 300
push 400
call add_cdecl
add esp,8

push eax
push offset szfmt
call crt_printf
add esp,8

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值