C语言调规则浅析
来源:互联网 发布:淘宝导航栏在线 编辑:程序博客网 时间:2024/05/17 22:40
函数调用中参数是通过堆栈或/和寄存器来传递的,根据调用时由调用函数或被调用函数来恢复堆栈,分为Standard和C两种调用规则,FASTCALL可以看作是Standard的特殊形式。
32 位 C语言编译器支持的调用规则 有 __stdcall (Standard), __cdecl (C) 和 __fastcall (FASTCALL), __cdecl为缺省值。
三种调用规则的特点如下:
右边两个能装入寄存器的参数进寄存器,其余参数从右到左进栈
被调用函数 通过寄存器传递参数,速度快 __cdecl 函数名前加下划线"_" 从右到左 调用函数 编译器为每次调用都生成堆栈清理代码,支持可变参数,如printf()以下简单的C程序和相应的汇编代码展示了三种调用规则的细节。
/**//*
* callconv - Calling Conventions
*/
int __stdcall stdcall_function(int p1, int p2)
...{
int n1;
int n2;
int ret;
n1 = p1;
n2 = p2;
ret = n1 + n2;
return 0;
}
int __cdecl cdecl_function(int p1, int p2)
...{
int n1, n2;
int ret;
n1 = p1;
n2 = p2;
ret = n1 + n2;
return ret;
}
int __cdecl cdecl_function_v(int p1, int p2, int v, ...)
...{
int n1, n2;
int ret;
n1 = p1;
n2 = p2;
ret = n1 + n2 + v;
return ret;
}
int __fastcall fastcall_function(int p1, double d1, int p2, double d2, int p3)
...{
int n1, n2;
double d;
int ret;
d = d1 + d2;
n1 = p1;
n2 = p2;
ret = n1 + n2 + p3;
return ret ;
}
int add(int p1, int p2)
...{
return (p1 + p2);
}
int main(void)
...{
int m, m1 = 1, m2 = 2, m3 = 3, m4 = 4;
double d1, d2;
d1 = 1.0;
d2 = 2.0;
m = stdcall_function(m1, m2);
m = cdecl_function(m1, m2);
m = cdecl_function_v(m1, m2, m3);
m = cdecl_function_v(m1, m2, m3, m4);
m = fastcall_function(m1, d1, m2, d2, m3);
return 0;
}
* callconv - Calling Conventions
*/
int __stdcall stdcall_function(int p1, int p2)
...{
int n1;
int n2;
int ret;
n1 = p1;
n2 = p2;
ret = n1 + n2;
return 0;
}
int __cdecl cdecl_function(int p1, int p2)
...{
int n1, n2;
int ret;
n1 = p1;
n2 = p2;
ret = n1 + n2;
return ret;
}
int __cdecl cdecl_function_v(int p1, int p2, int v, ...)
...{
int n1, n2;
int ret;
n1 = p1;
n2 = p2;
ret = n1 + n2 + v;
return ret;
}
int __fastcall fastcall_function(int p1, double d1, int p2, double d2, int p3)
...{
int n1, n2;
double d;
int ret;
d = d1 + d2;
n1 = p1;
n2 = p2;
ret = n1 + n2 + p3;
return ret ;
}
int add(int p1, int p2)
...{
return (p1 + p2);
}
int main(void)
...{
int m, m1 = 1, m2 = 2, m3 = 3, m4 = 4;
double d1, d2;
d1 = 1.0;
d2 = 2.0;
m = stdcall_function(m1, m2);
m = cdecl_function(m1, m2);
m = cdecl_function_v(m1, m2, m3);
m = cdecl_function_v(m1, m2, m3, m4);
m = fastcall_function(m1, d1, m2, d2, m3);
return 0;
}
TITLE C:Documents and Settings ootsrccallconvcallconv.c
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC _stdcall_function@8
_TEXT SEGMENT
_p1$ = 8
_p2$ = 12
_n1$ = -12
_n2$ = -4
_ret$ = -8
_stdcall_function@8 PROC NEAR
; 6 : ...{
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
; 7 : int n1;
; 8 : int n2;
; 9 : int ret;
; 10 :
; 11 : n1 = p1;
mov eax, DWORD PTR _p1$[ebp]
mov DWORD PTR _n1$[ebp], eax
; 12 : n2 = p2;
mov ecx, DWORD PTR _p2$[ebp]
mov DWORD PTR _n2$[ebp], ecx
; 13 :
; 14 : ret = n1 + n2;
mov edx, DWORD PTR _n1$[ebp]
add edx, DWORD PTR _n2$[ebp]
mov DWORD PTR _ret$[ebp], edx
; 15 :
; 16 : return 0;
xor eax, eax
; 17 : }
mov esp, ebp
pop ebp
ret 8
_stdcall_function@8 ENDP
_TEXT ENDS
PUBLIC _cdecl_function
_TEXT SEGMENT
_p1$ = 8
_p2$ = 12
_n1$ = -12
_n2$ = -4
_ret$ = -8
_cdecl_function PROC NEAR
; 20 : ...{
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
; 21 : int n1, n2;
; 22 :
; 23 : int ret;
; 24 :
; 25 : n1 = p1;
mov eax, DWORD PTR _p1$[ebp]
mov DWORD PTR _n1$[ebp], eax
; 26 : n2 = p2;
mov ecx, DWORD PTR _p2$[ebp]
mov DWORD PTR _n2$[ebp], ecx
; 27 :
; 28 : ret = n1 + n2;
mov edx, DWORD PTR _n1$[ebp]
add edx, DWORD PTR _n2$[ebp]
mov DWORD PTR _ret$[ebp], edx
; 29 :
; 30 : return ret;
mov eax, DWORD PTR _ret$[ebp]
; 31 : }
mov esp, ebp
pop ebp
ret 0
_cdecl_function ENDP
_TEXT ENDS
PUBLIC _cdecl_function_v
_TEXT SEGMENT
_p1$ = 8
_p2$ = 12
_v$ = 16
_n1$ = -12
_n2$ = -4
_ret$ = -8
_cdecl_function_v PROC NEAR
; 34 : ...{
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
; 35 : int n1, n2;
; 36 :
; 37 : int ret;
; 38 :
; 39 : n1 = p1;
mov eax, DWORD PTR _p1$[ebp]
mov DWORD PTR _n1$[ebp], eax
; 40 : n2 = p2;
mov ecx, DWORD PTR _p2$[ebp]
mov DWORD PTR _n2$[ebp], ecx
; 41 :
; 42 : ret = n1 + n2 + v;
mov edx, DWORD PTR _n1$[ebp]
add edx, DWORD PTR _n2$[ebp]
add edx, DWORD PTR _v$[ebp]
mov DWORD PTR _ret$[ebp], edx
; 43 :
; 44 : return ret;
mov eax, DWORD PTR _ret$[ebp]
; 45 : }
mov esp, ebp
pop ebp
ret 0
_cdecl_function_v ENDP
_TEXT ENDS
PUBLIC @fastcall_function@28
EXTRN __fltused:NEAR
_TEXT SEGMENT
_p1$ = -24
_d1$ = 8
_p2$ = -28
_d2$ = 16
_p3$ = 24
_n1$ = -20
_n2$ = -4
_d$ = -12
_ret$ = -16
@fastcall_function@28 PROC NEAR
; 48 : ...{
push ebp
mov ebp, esp
sub esp, 28 ; 0000001cH
mov DWORD PTR _p2$[ebp], edx
mov DWORD PTR _p1$[ebp], ecx
; 49 : int n1, n2;
; 50 : double d;
; 51 :
; 52 : int ret;
; 53 :
; 54 : d = d1 + d2;
fld QWORD PTR _d1$[ebp]
fadd QWORD PTR _d2$[ebp]
fstp QWORD PTR _d$[ebp]
; 55 :
; 56 : n1 = p1;
mov eax, DWORD PTR _p1$[ebp]
mov DWORD PTR _n1$[ebp], eax
; 57 : n2 = p2;
mov ecx, DWORD PTR _p2$[ebp]
mov DWORD PTR _n2$[ebp], ecx
; 58 :
; 59 : ret = n1 + n2 + p3;
mov edx, DWORD PTR _n1$[ebp]
add edx, DWORD PTR _n2$[ebp]
add edx, DWORD PTR _p3$[ebp]
mov DWORD PTR _ret$[ebp], edx
; 60 :
; 61 : return ret ;
mov eax, DWORD PTR _ret$[ebp]
; 62 : }
mov esp, ebp
pop ebp
ret 20 ; 00000014H
@fastcall_function@28 ENDP
_TEXT ENDS
PUBLIC _add
_TEXT SEGMENT
_p1$ = 8
_p2$ = 12
_add PROC NEAR
; 65 : ...{
push ebp
mov ebp, esp
; 66 : return (p1 + p2);
mov eax, DWORD PTR _p1$[ebp]
add eax, DWORD PTR _p2$[ebp]
; 67 : }
pop ebp
ret 0
_add ENDP
_TEXT ENDS
PUBLIC _main
_TEXT SEGMENT
_m$ = -32
_m1$ = -20
_m2$ = -24
_m3$ = -28
_m4$ = -36
_d1$ = -8
_d2$ = -16
_main PROC NEAR
; 70 : ...{
push ebp
mov ebp, esp
sub esp, 36 ; 00000024H
; 71 : int m, m1 = 1, m2 = 2, m3 = 3, m4 = 4;
mov DWORD PTR _m1$[ebp], 1
mov DWORD PTR _m2$[ebp], 2
mov DWORD PTR _m3$[ebp], 3
mov DWORD PTR _m4$[ebp], 4
; 72 :
; 73 : double d1, d2;
; 74 :
; 75 : d1 = 1.0;
mov DWORD PTR _d1$[ebp], 0
mov DWORD PTR _d1$[ebp+4], 1072693248 ; 3ff00000H
; 76 : d2 = 2.0;
mov DWORD PTR _d2$[ebp], 0
mov DWORD PTR _d2$[ebp+4], 1073741824 ; 40000000H
; 77 :
; 78 : m = stdcall_function(m1, m2);
mov eax, DWORD PTR _m2$[ebp]
push eax
mov ecx, DWORD PTR _m1$[ebp]
push ecx
call _stdcall_function@8
mov DWORD PTR _m$[ebp], eax
; 79 :
; 80 : m = cdecl_function(m1, m2);
mov edx, DWORD PTR _m2$[ebp]
push edx
mov eax, DWORD PTR _m1$[ebp]
push eax
call _cdecl_function
add esp, 8
mov DWORD PTR _m$[ebp], eax
; 81 :
; 82 : m = cdecl_function_v(m1, m2, m3);
mov ecx, DWORD PTR _m3$[ebp]
push ecx
mov edx, DWORD PTR _m2$[ebp]
push edx
mov eax, DWORD PTR _m1$[ebp]
push eax
call _cdecl_function_v
add esp, 12 ; 0000000cH
mov DWORD PTR _m$[ebp], eax
; 83 :
; 84 : m = cdecl_function_v(m1, m2, m3, m4);
mov ecx, DWORD PTR _m4$[ebp]
push ecx
mov edx, DWORD PTR _m3$[ebp]
push edx
mov eax, DWORD PTR _m2$[ebp]
push eax
mov ecx, DWORD PTR _m1$[ebp]
push ecx
call _cdecl_function_v
add esp, 16 ; 00000010H
mov DWORD PTR _m$[ebp], eax
; 85 :
; 86 : m = fastcall_function(m1, d1, m2, d2, m3);
mov edx, DWORD PTR _m3$[ebp]
push edx
mov eax, DWORD PTR _d2$[ebp+4]
push eax
mov ecx, DWORD PTR _d2$[ebp]
push ecx
mov edx, DWORD PTR _m2$[ebp]
mov eax, DWORD PTR _d1$[ebp+4]
push eax
mov ecx, DWORD PTR _d1$[ebp]
push ecx
mov ecx, DWORD PTR _m1$[ebp]
call @fastcall_function@28
mov DWORD PTR _m$[ebp], eax
; 87 :
; 88 : return 0;
xor eax, eax
; 89 : }
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC _stdcall_function@8
_TEXT SEGMENT
_p1$ = 8
_p2$ = 12
_n1$ = -12
_n2$ = -4
_ret$ = -8
_stdcall_function@8 PROC NEAR
; 6 : ...{
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
; 7 : int n1;
; 8 : int n2;
; 9 : int ret;
; 10 :
; 11 : n1 = p1;
mov eax, DWORD PTR _p1$[ebp]
mov DWORD PTR _n1$[ebp], eax
; 12 : n2 = p2;
mov ecx, DWORD PTR _p2$[ebp]
mov DWORD PTR _n2$[ebp], ecx
; 13 :
; 14 : ret = n1 + n2;
mov edx, DWORD PTR _n1$[ebp]
add edx, DWORD PTR _n2$[ebp]
mov DWORD PTR _ret$[ebp], edx
; 15 :
; 16 : return 0;
xor eax, eax
; 17 : }
mov esp, ebp
pop ebp
ret 8
_stdcall_function@8 ENDP
_TEXT ENDS
PUBLIC _cdecl_function
_TEXT SEGMENT
_p1$ = 8
_p2$ = 12
_n1$ = -12
_n2$ = -4
_ret$ = -8
_cdecl_function PROC NEAR
; 20 : ...{
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
; 21 : int n1, n2;
; 22 :
; 23 : int ret;
; 24 :
; 25 : n1 = p1;
mov eax, DWORD PTR _p1$[ebp]
mov DWORD PTR _n1$[ebp], eax
; 26 : n2 = p2;
mov ecx, DWORD PTR _p2$[ebp]
mov DWORD PTR _n2$[ebp], ecx
; 27 :
; 28 : ret = n1 + n2;
mov edx, DWORD PTR _n1$[ebp]
add edx, DWORD PTR _n2$[ebp]
mov DWORD PTR _ret$[ebp], edx
; 29 :
; 30 : return ret;
mov eax, DWORD PTR _ret$[ebp]
; 31 : }
mov esp, ebp
pop ebp
ret 0
_cdecl_function ENDP
_TEXT ENDS
PUBLIC _cdecl_function_v
_TEXT SEGMENT
_p1$ = 8
_p2$ = 12
_v$ = 16
_n1$ = -12
_n2$ = -4
_ret$ = -8
_cdecl_function_v PROC NEAR
; 34 : ...{
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
; 35 : int n1, n2;
; 36 :
; 37 : int ret;
; 38 :
; 39 : n1 = p1;
mov eax, DWORD PTR _p1$[ebp]
mov DWORD PTR _n1$[ebp], eax
; 40 : n2 = p2;
mov ecx, DWORD PTR _p2$[ebp]
mov DWORD PTR _n2$[ebp], ecx
; 41 :
; 42 : ret = n1 + n2 + v;
mov edx, DWORD PTR _n1$[ebp]
add edx, DWORD PTR _n2$[ebp]
add edx, DWORD PTR _v$[ebp]
mov DWORD PTR _ret$[ebp], edx
; 43 :
; 44 : return ret;
mov eax, DWORD PTR _ret$[ebp]
; 45 : }
mov esp, ebp
pop ebp
ret 0
_cdecl_function_v ENDP
_TEXT ENDS
PUBLIC @fastcall_function@28
EXTRN __fltused:NEAR
_TEXT SEGMENT
_p1$ = -24
_d1$ = 8
_p2$ = -28
_d2$ = 16
_p3$ = 24
_n1$ = -20
_n2$ = -4
_d$ = -12
_ret$ = -16
@fastcall_function@28 PROC NEAR
; 48 : ...{
push ebp
mov ebp, esp
sub esp, 28 ; 0000001cH
mov DWORD PTR _p2$[ebp], edx
mov DWORD PTR _p1$[ebp], ecx
; 49 : int n1, n2;
; 50 : double d;
; 51 :
; 52 : int ret;
; 53 :
; 54 : d = d1 + d2;
fld QWORD PTR _d1$[ebp]
fadd QWORD PTR _d2$[ebp]
fstp QWORD PTR _d$[ebp]
; 55 :
; 56 : n1 = p1;
mov eax, DWORD PTR _p1$[ebp]
mov DWORD PTR _n1$[ebp], eax
; 57 : n2 = p2;
mov ecx, DWORD PTR _p2$[ebp]
mov DWORD PTR _n2$[ebp], ecx
; 58 :
; 59 : ret = n1 + n2 + p3;
mov edx, DWORD PTR _n1$[ebp]
add edx, DWORD PTR _n2$[ebp]
add edx, DWORD PTR _p3$[ebp]
mov DWORD PTR _ret$[ebp], edx
; 60 :
; 61 : return ret ;
mov eax, DWORD PTR _ret$[ebp]
; 62 : }
mov esp, ebp
pop ebp
ret 20 ; 00000014H
@fastcall_function@28 ENDP
_TEXT ENDS
PUBLIC _add
_TEXT SEGMENT
_p1$ = 8
_p2$ = 12
_add PROC NEAR
; 65 : ...{
push ebp
mov ebp, esp
; 66 : return (p1 + p2);
mov eax, DWORD PTR _p1$[ebp]
add eax, DWORD PTR _p2$[ebp]
; 67 : }
pop ebp
ret 0
_add ENDP
_TEXT ENDS
PUBLIC _main
_TEXT SEGMENT
_m$ = -32
_m1$ = -20
_m2$ = -24
_m3$ = -28
_m4$ = -36
_d1$ = -8
_d2$ = -16
_main PROC NEAR
; 70 : ...{
push ebp
mov ebp, esp
sub esp, 36 ; 00000024H
; 71 : int m, m1 = 1, m2 = 2, m3 = 3, m4 = 4;
mov DWORD PTR _m1$[ebp], 1
mov DWORD PTR _m2$[ebp], 2
mov DWORD PTR _m3$[ebp], 3
mov DWORD PTR _m4$[ebp], 4
; 72 :
; 73 : double d1, d2;
; 74 :
; 75 : d1 = 1.0;
mov DWORD PTR _d1$[ebp], 0
mov DWORD PTR _d1$[ebp+4], 1072693248 ; 3ff00000H
; 76 : d2 = 2.0;
mov DWORD PTR _d2$[ebp], 0
mov DWORD PTR _d2$[ebp+4], 1073741824 ; 40000000H
; 77 :
; 78 : m = stdcall_function(m1, m2);
mov eax, DWORD PTR _m2$[ebp]
push eax
mov ecx, DWORD PTR _m1$[ebp]
push ecx
call _stdcall_function@8
mov DWORD PTR _m$[ebp], eax
; 79 :
; 80 : m = cdecl_function(m1, m2);
mov edx, DWORD PTR _m2$[ebp]
push edx
mov eax, DWORD PTR _m1$[ebp]
push eax
call _cdecl_function
add esp, 8
mov DWORD PTR _m$[ebp], eax
; 81 :
; 82 : m = cdecl_function_v(m1, m2, m3);
mov ecx, DWORD PTR _m3$[ebp]
push ecx
mov edx, DWORD PTR _m2$[ebp]
push edx
mov eax, DWORD PTR _m1$[ebp]
push eax
call _cdecl_function_v
add esp, 12 ; 0000000cH
mov DWORD PTR _m$[ebp], eax
; 83 :
; 84 : m = cdecl_function_v(m1, m2, m3, m4);
mov ecx, DWORD PTR _m4$[ebp]
push ecx
mov edx, DWORD PTR _m3$[ebp]
push edx
mov eax, DWORD PTR _m2$[ebp]
push eax
mov ecx, DWORD PTR _m1$[ebp]
push ecx
call _cdecl_function_v
add esp, 16 ; 00000010H
mov DWORD PTR _m$[ebp], eax
; 85 :
; 86 : m = fastcall_function(m1, d1, m2, d2, m3);
mov edx, DWORD PTR _m3$[ebp]
push edx
mov eax, DWORD PTR _d2$[ebp+4]
push eax
mov ecx, DWORD PTR _d2$[ebp]
push ecx
mov edx, DWORD PTR _m2$[ebp]
mov eax, DWORD PTR _d1$[ebp+4]
push eax
mov ecx, DWORD PTR _d1$[ebp]
push ecx
mov ecx, DWORD PTR _m1$[ebp]
call @fastcall_function@28
mov DWORD PTR _m$[ebp], eax
; 87 :
; 88 : return 0;
xor eax, eax
; 89 : }
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
- C语言调规则浅析
- C语言命名规则
- c语言命名规则
- C语言规则
- C语言命名规则
- C语言命名规则
- c语言命名规则
- C语言命名规则
- C语言命名规则
- c语言命名规则
- C语言函数浅析
- C语言编译器浅析
- C语言指针浅析
- c语言数据类型浅析
- C语言声明解读规则
- C语言声明优先级规则
- C语言声明优先级规则
- c语言变量名规则
- .NET官方编码方法和命名规则
- 如何实现无刷新的DropdownList联动效果
- C#编码标准--编码习惯
- 喜欢上了java.因为他不断进取,积极向上
- 灰度图像增强
- C语言调规则浅析
- 微软的人机交互之闲谈
- 什么是牛B的拍砖文章
- 程序毛病的代价
- 今天要出去玩了
- 开源(open source)英汉机器翻译 C#.NET 源代码 www.liebiao.net
- __cdecl __fastcall与 __stdcall
- 经验之谈:DHCP、网关和DNS地址的捆绑
- 交换机、集线器、路由器区别和作用