agn equal sit t
Eigentlich könnten Übersetzer machen, was sie wollen,
Speicher und Register beliebig verwenden
Hauptsache das resultierende Programm funktioniert im Anschluss
Das kann allerdings dann zu einem Problem werden,
wenn wir ein Unterprogramm verwenden wollen
welches von einem anderen Übersetzer erstellt wurde
vielleicht wegen einer anderen Programmiersprache
Um Interoperabilität zu gewährleisten
müssen sich die Übersetzer an eine Aufrufkonvention halten.
Zum Beispiel, wer welche Register bei einem Funktionsaufruf sichern muss.
Der Aufrufende muss sich um die flüchtigen Register kümmern
und die aufgerufene Funktion um die nicht flüchtigen,
sofern sie diese denn überhaupt verwendet.
Aber welche Register sind nun was?
Wir sind im Long Mode auf der 64-bit x86 Architektur.
Für uns spielen weder Segmentregister noch Kontroll- oder Diebakregister eine Rolle beim Funktionsaufruf.
Und da wir uns im Betriebssystem bewegen, ignorieren wir auch die SSE-Register,
sondern konzentrieren uns primär auf die Allzweck-Register,
um berücksichtigen Statusregister und Stapel sowie Instruktionszeiger.
Nach der System-5-ABI für 64-Bit sind diese zehn blau eingefärbten Register flüchtig definiert.
Auch Scratch oder ColorSafe genannt, müssen also von der aufrufenden Funktion zuerst gesichert werden.
Die anderen Register sind nicht flüchtig,
natürlich mit Ausnahme der Sonderfälle Stapel und Instruktionszeiger.
Wenn ich nun die flüchtigen Register E bei Verwendung sichern und später
wieder herstellen muss,
dann würden sich diese doch eigenen Daten im Anschluss an die
aufzurufende Funktion zu übermitteln.
Und das wird auch gemacht.
RDI wird beispielsweise für den ersten und RSI für den zweiten
Funktionsparameter verwendet,
während der Rückgabewert in rax geschrieben wird.
Wie sieht das nun in der Praxis aus?
Bei einem Funktionsaufruf mit eben zwei Parametern.
Schauen wir uns dazu den Aufruf von Funk mit Parameter 23 und 42 an.
Der Resultieren der Assembler-Code für den Aufruf könnte in etwa wie folgt aussehen.
Dabei verwende ich hier die Intel-Syndex, wie sie auch von unserem NetWide-Assembler verwendet wird.
Bei dieser wird zuerst das Ziel, dann die Quelle genannt.
Im Gegensatz zur AT&T-Syndex, die genau anders herum ist.
Aber aufgrund zusätzlicher Zeichen leicht identifiziert werden kann, wie dem Prozentzeichen vor Registernamen.
Letzteres wird übrigens standardmäßig beim InlineAssembly und in ObjectDAMP verwendet.
Als erstes werden, sofern nötig, flüchtige Register gesichert, beispielsweise R9.
Anschließend werden die Parameter in die entsprechenden Register geschrieben.
0x2a entspricht 42 dem zweiten Parameter und wird somit in RSI geschrieben.
0x17 für 23 als ersten Parameter in RDI.
Der Compiler generiert, wie hier zu sehen, für kleinere Zahlen innerhalb der 32-Bit-Grenze
ein Move nach ESI statt RSI.
Das ist valit, da dabei automatisch die oberen 32-Bit von RSI auf Null gesetzt werden.
Der Aufruf hat also die gleiche Wirkung, es werden sich durch diese Variante jedoch
ein paar Bytes im Maschinencode gespart.
Presenters
Zugänglich über
Offener Zugang
Dauer
00:07:45 Min
Aufnahmedatum
2020-08-10
Hochgeladen am
2021-09-20 18:56:41
Sprache
de-DE
Kontextsicherung und Parameterübergabe nach System-V-ABI für Aufgabe 4 der Lehrveranstaltung Betriebssysteme.
Folien und Transkript zum Video.