2012-12-01 18 views
5

Ich habe während des Studiums von Spielregeln mit C++ Konventionen getroffen.Einfach und einfach, warum verwenden wir _stdcall?

In einer früheren Frage sagte jemand, dass MSDN _stdcall nicht sehr gut erklärt - ich stimme zu.

Wozu dienen hauptsächlich Konventionen wie _stdcall? Spielt es eine Rolle, in welcher Reihenfolge die Argumente auf den Stapel gelegt werden? Wie reduziert es die Größe des Codes in X86 (wie jemand anders angegeben hat)?

+3

Wenn eine Funktion viele Argumente und viele Aufrufer hat, ist es für den Angerufenen sinnvoller, den Stapel an vielen Stellen anstatt an jedem Aufrufer an einer Stelle aufzuräumen. – ildjarn

+0

Fragen Sie, was das Design der verschiedenen Aufrufkonventionen antrieb, oder warum müssen sie überhaupt spezifiziert werden? – StoryTeller

+0

Mehr einfach, warum sie tatsächlich verwendet werden, in einfachen Menschen sprechen: P Die MSDN war ziemlich komplex und scheint ziemlich viele Leute verwirrt zu haben! – Dezachu

Antwort

8

Der Grund für einige Aufrufkonvention ist ziemlich einfach: so dass der Anrufer und der Angerufene darüber einig sind, wie die Dinge funktionieren. Ohne sie weiß der Aufrufer nicht, wo er Argumente ablegen soll, wenn er eine bestimmte Funktion aufruft.

Warum für Microsoft auf die spezifischen Details von _stdcall entschieden, das ist weitgehend historischen. Unter MS-DOS waren alle Aufrufe registerbasiert, sodass für alle OS-Aufrufe eine Assemblersprache oder merkwürdige Erweiterungen für die meisten höheren Sprachen erforderlich waren.

Bei der ersten Verwendung von Windows verwendeten sie die Aufrufkonvention cdecl, hauptsächlich weil der Compiler dies standardmäßig getan hatte. Zumindest nach Gerüchten, kurz bevor sie bereit waren, Windows 1.0 zu veröffentlichen, wechselten sie auf die Pascal-Aufrufkonvention, weil es effizienter genug war, dass Windows unter anderem auf weniger Disketten passen konnte. Unabhängig von den präzisen Details machte die Pascal-Aufrufkonvention den Code ein wenig kleiner, weil die aufgerufene Funktion die Argumente vom Stapel löschte, anstatt sie überall aufzuräumen, wo die Funktion aufgerufen wurde. Für jede Funktion, die von mindestens 2 verschiedenen Orten aufgerufen wurde, ist das ein Gewinn (und wenn es woanders ist).

Dann begannen sie mit der Arbeit an OS/2 und erfanden eine weitere Aufrufkonvention (syscall).

Dann kam natürlich Win32. Es gab nicht viel falsch mit syscall aus technischer Sicht, aber (ich denke mal) alles, was mit OS/2 zusammenhing, wurde als verdorben angesehen, also musste syscall gehen. Das Ergebnis war etwas gerade genug, um einen neuen Namen zu rechtfertigen. Fairerweise ist das ein bisschen übertrieben: Sie haben einen wirklich nützlichen Zusatz hinzugefügt: Sie haben die Anzahl der Bytes der Argumente in jeden Funktionsnamen kodiert. Wenn Sie also beispielsweise einen falschen Prototyp für eine Funktion angegeben haben, würde der Code nicht funktionieren 't Link, anstatt mit einem Missverhältnis zwischen Anrufer und Angerufener enden, die zu viel ernsteren Problemen führen könnte.

Zum größten Teil kommt es aber wirklich auf den ursprünglichen Punkt zurück: Die genauen Details der Aufrufkonvention spielen keine so große Rolle, solange man sie nicht komplett durcheinanderbringt. Es kommt vor allem darauf an, dass der Anrufer und der Angerufene dem zustimmen. Wenn also ein Compiler weiß, welche Parameter eine Funktion akzeptiert, kann er Code generieren, um diese Parameter korrekt zu konfigurieren (und beide stimmen dem zu) wie die Stapelbereinigung gehandhabt wird, etc.)

+0

Ahh, gut, das erklärt, warum 5 sogar überhaupt existieren; Ich hätte gedacht, sie würden dasjenige behalten, das am effizientesten und aktuellsten zu sein scheint und den Rest verschrottet! Prost. Das erklärt immer noch nicht ganz, warum wir überhaupt einen benutzen müssen? Liegt es nur daran, dass verschiedene Compiler unterschiedliche Standard-Aufrufkonventionen verwenden, also verwenden wir eine einheitliche Aufrufmethode für alle Compiler/Betriebssysteme? Wenn ja, ist es eine gute Übung für mich, sie zu benutzen? Oder sollte ich mich während meiner Ausbildung nicht um sie kümmern? – Dezachu

+0

Aufrufkonventionen sind eine der Sachen, die Compiler-Autoren debattieren, damit sie nicht langweilig werden :) Es ist ein Low-Level-Detail, das Sie lange ignorieren können. –

+0

auch, einige Aufrufkonventionen helfen, zusätzliche "Funktionen" zur Verfügung zu stellen, die andere Aufrufkonventionen nicht oder schwieriger zu bieten haben. Zum Beispiel platziert 'cdecl' die Stapelbereinigung für den Aufrufer anstelle des Aufrufers. Dies vereinfacht Argumente mit variabler Länge leichter, da nur der Aufrufer weiß, wie groß der Stapel sein wird. Der Anrufer ist in diesem Fall der Einzige, der den Stack aufräumen kann und auch dafür verantwortlich ist. Für 'stdcall' könnte das nur funktionieren, wenn der Aufrufer den' callee' darüber informiert, wie groß der Stack sein wird, aber ich habe nicht gesehen, dass dies auf diese Weise implementiert ist. –

Verwandte Themen