Пример соглашений о вызовах
В листинге 6-1 показан пример всех соглашений о вызовах из окна Disassembly отладчика Visual C++. В нем объединены все инструкции, рассмотренные до настоящего момента, и соглашения о вызовах. Исходный код примера (CALLING.CPP) находится на сопровождающем компакт-диске.
Для облегчения просмотра код листинга 6-1 имеет отладочную структуру; кроме того, код фактически ничего не делает. Каждая функция просто вызывается с подходящим соглашением о вызове. Обратите особое внимание на то, как размещены параметры в функциях, и как очищается стек. Чтобы сделать листинг более легким для чтения, между функциями вставлены инструкции NOP.
Листинг 6-1 Пример соглашений о вызовах
6: // Строки , передаваемые каждой функции -
7: static char * g_szStdCall = "_stdcall";
8: static char * g_szCdeclCall = "_cdecl";
9: static char * g_szFastCall = "_fastcall" ;
10: static char * g_szNakedCall = "_naked" ;
11:
12: // extern "С" отключает всю декорацию имен C++ .
13: extern "С"
14: {
15: .
16: // _cdecl-функция
17: void CDeclFunction { char * szString ,
18: unsigned long ulLong ,
19: char chChar ) ;
20:
21: // stdcall-функция
22: void _stdcall StdCallFunction ( char * szString ,
23: unsigned long ulLong ,
24: char chChar ) ;
25: // _fastcall-функция
26: void _fastcall FastCallFunction ( char * szString ,
27: unsigned long ulLong ,
28: char chChar ) ;
29:
30: /'/ "Голая" функция. Нет спецификатора ни для определения,
31: //ни для декларирования функции.
32: int NakedCallFunction ( char * szString ,
33: unsigned long ulLong ,
34: ' char chChar ) ;
35: }
36:
37: void main ( void )
38: {
00401000 55 push ebp
00401001 8B EC mov ebp,esp
00401003 53 push ebx
00401004 56 push esi
00401005 57 push edi
39: // Вызвать каждую функцию для генерации кода. Я разделяю
40: // каждую функцию парой NOP-байтов, чтобы облегчить чтение
41: // кода дизассемблера
42: _asm NOP _asm NOP
00401006 90 nор
00401007 90 nор
43: CDeclFunction ( g_szCdeclCall , 1 , 'а' ) ;
00401008 6А 61 push 61h
0040100A 6A 01 push 1
0040100C Al 14 30 40 00 mov eax,[g_szCdeclCall (00403014)]
00401011 50 push eax
00401012 E8 45 00 00 00 call CDeclFunction (0040105с)
00401017 83 C4 ОС add esp,OCh
44: _asm NOP _asm NOP
0040101A 90 nор
0040101B 90 nор
45: StdCallFunction ( g_szStdCall , 2 , 'b' ) ;
0040101C 6A 62 push 62h
0040101E 6A 02 push 2
00401020 8B OD 10 30 40 00 mov ecx,dword ptr
[g_szStdCall (00403010)]
00401026 51 push ecx
00401027 E8 3D 00 00 00 call StdCallFunction (00401069)
46: _asm NOP _asm NOP
0040102C 90 nор
0040102D 90 nор
47: FastCallFunction ( g_szFastCall , 3 , 'c' ) ;
0040102E 6A 63 push 63h
00401030 BA 03 00 00 00 mov edx,3
00401035 8B OD 18 30 40 00 mov ecx,dword ptr
[g_szFastCall (00403018)]
0040103В Е8 38 00 00 00 call FastCallFunction (00401078)
48: _asm NOP _asm NOP
00401040 90 nор
00401041 90 nор
49: NakedCallFunction ( g_szNakedCall , 4 , 'd' ) ;
00401042 6A 64 , push 64h
00401044 6A 04 push 4
00401046 8B 15 1C 30 40 00 mov edx,dword ptr
[g-_szNakedCall (0040301с)]
0040104C 52 push edx
0040104D E8 40 00 00 00 call NakedCallFunction (00401092)
00401052 83 C4 ОС add esp,OCh
50: _asm NOP _asm NOP
00401055 90 nор
00401056 90 nор
51:
52: }
00401057 5F pop edi
00401058 5E pop esi
00401059 5B pop ebx
0040105A 5D pop ebp
0040105В СЗ ret
53:
54: void CDeclFunction ( char * szString ,
55: unsigned long ulLong ,
56: char chChar )
57: {
0040105C 55 push ebp
0040105D 8B EC mov ebp,esp
0040105F 53 push ebx
00401060 56 push esi
00401061 57 push edi 58: _asm NOP _asm NOP
00401062 90 nор
00401063 90 nор
59: }
00401064 5F pop edi
00401065 5E pop esi
00401066 5B pop ebx
00401067 5D pop ebp
00401068 C3 ret
60:
61: void _stdcall StdCallFunction ( char * szString ,
62: unsigned long ulLong ,
63: char chChar )
64: {
00401069 55 push ' ebp
0040106A-8B EC mov ebp,esp
0040106C 53 push ebx
0040106D 56 push esi
0040.106E 57 push edi
65: _asm NOP _asm NOP
0040106F 90 nор
00401070 90 nор
66: }
00401071 5F pop edi
00401072 5E pop esi
00401073 5B pop ebx
00401074 5D pop ebp
00401075 C2 ОС 00 ret OCh
67:
68: void _fastcall FastCallFunction ( char * szString ,
69: unsigned long ulLong ,
70: char chChar )
71: {
00401078 55 push ebp
00401079 8B EC mov ebp,esp
0040107B 83 EC 08 sub , esp,8
0040107E 53 push ebx
0040107F 56 push esi
00401080 57 push edi
00401081 89 55 F8 mov dword ptr [ebp-8],edx
00401084 89 4D FC mov dword ptr [ebp-4],ecx
72: _asm NOP _asm NOP
00401087 90 nор
00401088 90 nор
73: }
00401089 5F pop edi
0040108A 5E pop esi
0040108В 5В pop ebx
0040108C 8В Е5 , mov esp,ebp
0040108Е 5D pop ebp
0040108F C2 04 00 ret 4
74:
75: _declspec(naked) int NakedCa11Function ( char * szString ,
76: unsigned long ulLong ,
77: . char chChar )
78: {
00401092 90 nор
00401093 9.0 nор
79: _asm NOP _asm NOP
80: // Голые функции должны явно выполнять возврат.
81: _asm RET
00401094 СЗ ret