Ich werde eine weitere Antwort hinzufügen, um einige der tangentialen Diskussionen anzusprechen, die stattgefunden haben.
Das C ABI (Application Binary Interface) forderte ursprünglich die Übergabe von Argumenten auf dem Stapel in umgekehrter Reihenfolge (dh von rechts nach links verschoben), wobei der Aufrufer auch den Stapelspeicher freigibt. Das moderne ABI verwendet tatsächlich Register zum Übergeben von Argumenten, aber viele der Überlegungen zum Mangeln gehen auf das Übergeben des ursprünglichen Stapelarguments zurück.
Im Gegensatz dazu schob der ursprüngliche Pascal ABI die Argumente von links nach rechts, und der Angerufene musste die Argumente platzen lassen. Der ursprüngliche C ABI ist dem ursprünglichen Pascal ABI in zwei wichtigen Punkten überlegen. Die Argument-Push-Reihenfolge bedeutet, dass der Stapelversatz des ersten Arguments immer bekannt ist. Dies ermöglicht Funktionen mit einer unbekannten Anzahl von Argumenten, wobei die frühen Argumente steuern, wie viele andere Argumente es gibt (ala printf
).
Die zweite Art und Weise, in der der C ABI überlegen ist, ist das Verhalten, falls sich Anrufer und Angerufene nicht darüber einig sind, wie viele Argumente es gibt. Im Fall C passiert nichts Schlimmes, solange Sie nicht auf Argumente zugreifen, die über das letzte hinausgehen. In Pascal wird die falsche Anzahl von Argumenten aus dem Stapel entfernt und der gesamte Stapel ist beschädigt.
Das ursprüngliche Windows 3.1 ABI basierte auf Pascal. Als solches wurde der Pascal ABI verwendet (Argumente in der Reihenfolge von links nach rechts, Callee Pops). Da eine Nichtübereinstimmung der Argumentnummer zu einer Stapelbeschädigung führen kann, wurde ein Mangling-Schema gebildet. Jeder Funktionsname wurde mit einer Zahl entstellt, die die Größe seiner Argumente in Bytes angibt. Also auf 16-Bit-Maschine die folgende Funktion (C-Syntax):
int function(int a)
Wurde verstümmelt function@2
, weil int
es zwei Bytes breit ist. Dies wurde durchgeführt, damit der Linker die Funktion nicht findet, wenn die Deklaration und Definition nicht übereinstimmen, anstatt den Stapel zur Laufzeit zu beschädigen. Wenn das Programm dagegen verknüpft ist, können Sie sicher sein, dass am Ende des Aufrufs die richtige Anzahl von Bytes aus dem Stapel entfernt wird.
32-Bit-Windows und höher verwenden stdcall
stattdessen das ABI. Es ähnelt dem Pascal ABI, außer dass die Push-Reihenfolge wie in C von rechts nach links ist. Wie beim Pascal ABI werden beim Durchführen des Namens die Byte-Größe der Argumente in den Funktionsnamen zerlegt, um eine Stapelbeschädigung zu vermeiden.
Im Gegensatz zu Behauptungen, die an anderer Stelle hier gemacht wurden, werden die Funktionsnamen vom C ABI selbst in Visual Studio nicht entstellt. Umgekehrt sind Mangling-Funktionen, die mit der stdcall
ABI-Spezifikation dekoriert sind, nicht nur für VS verfügbar. GCC unterstützt dieses ABI auch beim Kompilieren für Linux. Dies wird häufig von Wine verwendet, das einen eigenen Loader verwendet, um die Laufzeitverknüpfung von Linux-kompilierten Binärdateien mit Windows-kompilierten DLLs zu ermöglichen.