Aggiungerò un'altra risposta, per affrontare alcune delle discussioni tangenziali che hanno avuto luogo.
L'ABI C (interfaccia binaria dell'applicazione) originariamente richiedeva il passaggio di argomenti sullo stack in ordine inverso (ovvero, spinto da destra a sinistra), dove il chiamante libera anche l'archiviazione dello stack. L'ABI moderno utilizza effettivamente i registri per passare argomenti, ma molte delle considerazioni mangling risalgono al passaggio dell'argomento stack originale.
L'ABI originale di Pascal, al contrario, ha spinto gli argomenti da sinistra a destra e la call ha dovuto far saltare gli argomenti. L'ABI C originale è superiore all'ABI originale Pascal in due punti importanti. L'ordine push dell'argomento indica che l'offset dello stack del primo argomento è sempre noto, consentendo funzioni che hanno un numero sconosciuto di argomenti, dove gli argomenti iniziali controllano quanti altri argomenti ci sono (ala printf
).
Il secondo modo in cui l'ABI C è superiore è il comportamento nel caso in cui il chiamante e il chiamante non siano d'accordo su quanti argomenti ci siano. Nel caso C, fintanto che in realtà non accedi agli argomenti oltre l'ultimo, non succede nulla di brutto. In Pascal, il numero errato di argomenti viene estratto dallo stack e l'intero stack è danneggiato.
L'ABI originale di Windows 3.1 era basato su Pascal. Come tale, ha usato l'ABI di Pascal (argomenti nell'ordine da sinistra a destra, chiamate di chiamata). Poiché qualsiasi discrepanza nel numero dell'argomento potrebbe portare alla corruzione impilata, si è formato uno schema di demolizione. Ogni nome di funzione è stato modificato con un numero che indica la dimensione, in byte, dei suoi argomenti. Quindi, sulla macchina a 16 bit, la seguente funzione (sintassi C):
int function(int a)
È stato rovinato function@2
, perché int
è largo due byte. Ciò è stato fatto in modo che se la dichiarazione e la definizione non corrispondono, il linker non riuscirà a trovare la funzione anziché corrompere lo stack in fase di esecuzione. Al contrario, se il programma si collega, allora puoi essere sicuro che il numero corretto di byte sia estratto dallo stack alla fine della chiamata.
Windows a 32 bit e successivi utilizzano stdcall
invece l' ABI. È simile all'ABI di Pascal, tranne per il fatto che l'ordine di spinta è come in C, da destra a sinistra. Come l'ABI di Pascal, il nome mangling modifica le dimensioni del byte degli argomenti nel nome della funzione per evitare il danneggiamento dello stack.
A differenza delle affermazioni fatte altrove, la C ABI non altera i nomi delle funzioni, nemmeno su Visual Studio. Al contrario, le funzioni di manipolazione decorate con le stdcall
specifiche ABI non sono esclusive di VS. GCC supporta anche questa ABI, anche durante la compilazione per Linux. Questo è ampiamente utilizzato da Wine , che utilizza il proprio caricatore per consentire il collegamento in fase di esecuzione dei binari compilati di Linux alle DLL compilate di Windows.