Tradizionalmente, le chiamate di funzione C vengono eseguite con il chiamante che inserisce alcuni parametri nello stack, chiamando la funzione, e quindi apre lo stack per pulire gli argomenti inseriti.
/* example of __cdecl */
push arg1
push arg2
push arg3
call function
add sp,12 // effectively "pop; pop; pop"
Nota: la convenzione di default - mostrata sopra - è conosciuta come __cdecl.
L'altra convenzione più popolare è __stdcall. In esso i parametri vengono nuovamente spinti dal chiamante, ma lo stack viene ripulito dal destinatario. È la convenzione standard per le funzioni API Win32 (come definito dalla macro WINAPI in), ed è talvolta chiamata anche convenzione di chiamata "Pascal".
/* example of __stdcall */
push arg1
push arg2
push arg3
call function // no stack cleanup - callee does this
Questo appare come un dettaglio tecnico minore, ma se c'è un disaccordo su come la pila è gestito tra il chiamante e il chiamato, lo stack saranno distrutti in un modo che è improbabile che possa essere recuperato. Poiché __stdcall esegue il cleanup dello stack, il codice (molto piccolo) per eseguire questa attività si trova in una sola posizione, anziché essere duplicato in ogni chiamante come in __cdecl. Ciò rende il codice leggermente più piccolo, sebbene l'impatto sulle dimensioni sia visibile solo nei programmi di grandi dimensioni.
Le funzioni variabili come printf() sono quasi impossibili da ottenere con __stdcall, perché solo il chiamante sa davvero quanti argomenti sono stati passati per pulirli. Il callee può fare alcune buone ipotesi (ad esempio, osservando una stringa di formato), ma la pulizia dello stack dovrebbe essere determinata dalla logica effettiva della funzione, non dal meccanismo della convenzione di chiamata stessa. Quindi solo __cdecl supporta le funzioni variadiche in modo che il chiamante possa eseguire la pulizia.
Decorazioni nome simbolo linker: Come menzionato in un punto elenco sopra, chiamare una funzione con la convenzione "errata" può essere disastroso, quindi Microsoft ha un meccanismo per evitare che ciò accada. Funziona bene, anche se può essere esasperante se non si conoscono le ragioni. Hanno scelto di risolvere questo codificando la convenzione di chiamata nei nomi di funzione di basso livello con caratteri aggiuntivi (che sono spesso chiamati "decorazioni"), e questi sono trattati come nomi non collegati dal linker. La convenzione di chiamata predefinita è __cdecl, ma ognuno può essere richiesto esplicitamente con/G? parametro per il compilatore.
__cdecl (cl/Gd ...)
Tutti i nomi delle funzioni di questo tipo sono preceduti dal prefisso un carattere di sottolineatura, e il numero di parametri non importa, perché il chiamante è responsabile per la messa a punto dello stack e lo stack di pulizia. È possibile che un chiamante e un chiamato si confondano sul numero di parametri effettivamente passati, ma almeno la disciplina dello stack viene mantenuta correttamente.
__stdcall (cl/Gz ...)
Questi nomi di funzione sono prefissati con una sottolineatura e aggiunti con @ più il numero di byte di parametri passati. Con questo meccanismo, non è possibile chiamare una funzione con il tipo "sbagliato" o anche con un numero errato di parametri.
__fastcall (cl/Gr ...)
Questi i nomi delle funzioni iniziano con un segno @ e hanno come suffisso il conteggio @parameter, proprio come __stdcall.
Esempi:
Declaration -----------------------> decorated name
void __cdecl foo(void); -----------------------> _foo
void __cdecl foo(int a); -----------------------> _foo
void __cdecl foo(int a, int b); -----------------------> _foo
void __stdcall foo(void); -----------------------> [email protected]
void __stdcall foo(int a); -----------------------> [email protected]
void __stdcall foo(int a, int b); -----------------------> [email protected]
void __fastcall foo(void); -----------------------> @[email protected]
void __fastcall foo(int a); -----------------------> @[email protected]
void __fastcall foo(int a, int b); -----------------------> @[email protected]
'__stdcall' e' __cdecl' differiscono solo per la responsabilità per la pulizia dopo il ritorno (e la decorazione). Il passaggio degli argomenti è lo stesso per entrambi (da destra a sinistra). Quello che stai descrivendo è la convenzione di chiamata Pascal. – a3f