__stdcall的名字修饰约定
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了__stdcall的名字修饰约定相关的知识,希望对你有一定的参考价值。
参考技术A1、修饰名(Decoration name)
“C”或者“C++”函数在内部(编译和链接)通过修饰名识别。修饰名是编译器在编译函数定义或者原
型时生成的字符串。有些情况下使用函数的修饰名是必要的,如在模块定义文件里头指定输出“C++”重载函数、构造函数、析构函数,又如在汇编代码里调用“C””或“C++”函数等。
修饰名由函数名、类名、调用约定、返回类型、参数等共同决定。
2、名字修饰约定随调用约定和编译种类(C或C++)的不同而变化。函数名修饰约定随编译种类和调用约定
的不同而不同,下面分别说明。
a、C编译时函数名修饰约定规则:
__stdcall调用约定在输出函数名前加上一个下划线前缀,后面加上一个“@”符号和其参数的字节数,
格式为_functionname@number。
__cdecl调用约定仅在输出函数名前加上一个下划线前缀,格式为_functionname。
__fastcall调用约定在输出函数名前加上一个“@”符号,后面也是一个“@”符号和其参数的字节数,
格式为@functionname@number。
它们均不改变输出函数名中的字符大小写,这和PASCAL调用约定不同,PASCAL约定输出的函数名无任何修饰且全部大写。
b、C++编译时函数名修饰约定规则:
__stdcall调用约定:
1、以“?”标识函数名的开始,后跟函数名;
2、函数名后面以“@@YG”标识参数表的开始,后跟参数表;
3、参数表以代号表示:
X--void ,
D--char,
E--unsigned char,
F--short,
H--int,
I--unsigned int,
J--long,
K--unsigned long,
M--float,
N--double,
_N--bool,
....
PA--表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以“0”代替,一个“0”代
表一次重复;
4、参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前
;
5、参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。
其格式为“?functionname@@YG*****@Z”或“?functionname@@YG*XZ”,例如
int Test1(char *var1,unsigned long)-----“?Test1@@YGHPADK@Z”
void Test2() -----“?Test2@@YGXXZ”
__cdecl调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的“@@YG”变为“@@YA”。
__fastcall调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的“@@YG”变为“@@YI”。
VC++对函数的缺省声明是__cdecl,将只能被C/C++调用.
6 用法举例
BOOL _declspec(dllexport)_stdcall InstallHook()
hkb = SetWindowsHookEx(WH_KEYBOARD,
(HOOKPROC)KeyboardProc,
hins,
0);
return TRUE;
函数调用约定
vc6.0:
int
__stdcall/__cdecl/__fastcall add(int x, int y)
{
return x+y;
}
void main()
{
add(2,3);
}
1.__stdcall:
1: int __stdcall add(int x, int y)
2: {
00401020 push
ebp
00401021 mov ebp,esp
00401023 sub esp,40h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 lea edi,[ebp-40h]
0040102C mov ecx,10h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr [edi]
3: return x+y;
00401038
mov eax,dword ptr [ebp+8]
0040103B add
eax,dword ptr [ebp+0Ch]
4: }
0040103E pop edi
0040103F pop esi
00401040 pop ebx
00401041 mov esp,ebp
00401043 pop ebp
00401044
ret 8
5:
6:
7: void main()
8: {
00401050 push ebp
00401051 mov ebp,esp
00401053 sub esp,40h
00401056 push ebx
00401057 push esi
00401058 push edi
00401059 lea edi,[ebp-40h]
0040105C mov ecx,10h
00401061 mov eax,0CCCCCCCCh
00401066 rep stos dword ptr [edi]
9: add(2,3);
00401068 push
3
0040106A push 2
0040106C call @ILT+0(add) (00401005)
10: }
00401071 pop
edi
00401072 pop esi
00401073 pop ebx
00401074 add esp,40h
00401077 cmp ebp,esp
00401079 call __chkesp (00401090)
0040107E mov esp,ebp
00401080 pop ebp
00401081 ret
00401005 jmp add (00401020)
2.__cdecl:
1: int __cdecl add(int x, int y)
2: {
00401020 push
ebp
00401021 mov ebp,esp
00401023 sub esp,40h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 lea edi,[ebp-40h]
0040102C mov ecx,10h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr [edi]
3: return x+y;
00401038
mov eax,dword ptr [ebp+8]
0040103B add
eax,dword ptr [ebp+0Ch]
4: }
0040103E pop edi
0040103F pop esi
00401040 pop ebx
00401041 mov esp,ebp
00401043 pop ebp
00401044
ret
5:
6:
7: void main()
8: {
00401050 push ebp
00401051 mov ebp,esp
00401053 sub esp,40h
00401056 push ebx
00401057 push esi
00401058 push edi
00401059 lea edi,[ebp-40h]
0040105C mov ecx,10h
00401061 mov eax,0CCCCCCCCh
00401066 rep stos dword ptr [edi]
9: add(2,3);
00401068 push
3
0040106A push 2
0040106C call @ILT+10(add) (0040100f)
00401071 add
esp,8
10: }
00401074
pop edi
00401075 pop esi
00401076 pop ebx
00401077 add esp,40h
0040107A cmp ebp,esp
0040107C call __chkesp (00401090)
00401081 mov esp,ebp
00401083 pop ebp
00401084 ret
0040100F jmp add (00401020)
3.__fastcall
1: int __fastcall add(int x, int y)
2: {
00401020 push
ebp
00401021 mov ebp,esp
00401023 sub esp,48h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 push
ecx
0040102A lea edi,[ebp-48h]
0040102D mov ecx,12h
00401032 mov eax,0CCCCCCCCh
00401037 rep stos dword ptr [edi]
0040103A mov dword ptr [ebp-8],edx
0040103D mov dword ptr [ebp-4],ecx
3: return x+y;
00401040
mov eax,dword ptr [ebp-4]
00401043 add
eax,dword ptr [ebp-8]
4: }
00401046 pop edi
00401047 pop esi
00401048 pop ebx
00401049 mov esp,ebp
0040104B pop ebp
0040104C ret
5:
6:
7: void main()
8: {
00401050 push
ebp
00401051 mov ebp,esp
00401053 sub esp,40h
00401056 push ebx
00401057 push esi
00401058 push edi
00401059 lea edi,[ebp-40h]
0040105C mov ecx,10h
00401061 mov eax,0CCCCCCCCh
00401066 rep stos dword ptr [edi]
9: add(2,3);
mov
edx,3
0040106D 00401072 call @ILT+15(add) (00401014)
10: }
00401077 pop
edi
00401078 pop esi
00401079 pop ebx
0040107A add esp,40h
0040107D cmp ebp,esp
0040107F call __chkesp (00401090)
00401084 mov esp,ebp
00401086 pop ebp
00401087 ret
00401014 jmp add (00401020)
====================================================================================
1: int __fastcall add(int x, int y, int z)
2: {
0040D480 push
ebp
0040D481 mov ebp,esp
0040D483 sub esp,48h
0040D486 push ebx
0040D487 push esi
0040D488 push edi
0040D489 push ecx
0040D48A lea edi,[ebp-48h]
0040D48D mov ecx,12h
0040D492 mov eax,0CCCCCCCCh
0040D497 rep stos dword ptr [edi]
0040D499 pop ecx
0040D49A mov dword ptr [ebp-8],edx
0040D49D mov dword ptr [ebp-4],ecx
3: return x+y+z;
0040D4A0
mov eax,dword ptr [ebp-4]
0040D4A3 add
eax,dword ptr [ebp-8]
0040D4A6 add eax,dword
ptr [ebp+8]
4: }
0040D4A9
pop edi
0040D4AA pop esi
0040D4AB pop ebx
0040D4AC mov esp,ebp
0040D4AE pop ebp
0040D4AF ret
4
5:
6:
7:
void main()
8: {
00401050
push ebp
00401051 mov ebp,esp
00401053 sub esp,40h
00401056 push ebx
00401057 push esi
00401058 push edi
00401059 lea edi,[ebp-40h]
0040105C mov ecx,10h
00401061 mov eax,0CCCCCCCCh
00401066 rep stos dword ptr [edi]
9: add(2,3,4);
push 4
0040106A mov edx,3
0040106F mov ecx,2
00401074 call @ILT+20(add) (00401019)
10: }
00401079 pop
edi
0040107A pop esi
0040107B pop ebx
0040107C add esp,40h
0040107F cmp ebp,esp
00401081 call __chkesp (00401090)
00401086 mov esp,ebp
00401088 pop ebp
00401089 ret
00401019 jmp add (0040d480)
以上是关于__stdcall的名字修饰约定的主要内容,如果未能解决你的问题,请参考以下文章