============ Call und Ret [TOC] ============ Am Tag 2 haben wir einige Assembler Befehle kennen und verstehen gelernt. Ein paar Dinge müssen wir aber noch genauer anschauen, um sie *wirklich* zu verstehen: - Was tun die Assembler Befehle `call` und `ret` ganz genau? - Was tut `push` und `pop` und wieso werden sie hier benötigt? Zweites Beispiel ================ :import: day03/second.c [stripped] Mit *--[SHELL(path=day03)]----------------------------------------------------* | | | gcc-4.8 -S -fno-asynchronous-unwind-tables second.c | | | *-------------------------------------------------------------------------* erzeugen wir den Assembler Code :import: day03/second.s Was tut Call und Ret? ===================== Beide Assembler Befehle ändern das `%rip` Register. Damit wird als nicht der im Text-Segment folgende Maschinenbefehl ausgeführt sondern es wird gesprungen. Stellt sich also die Frage wieso man nicht einfach den `jmp` Befehl benutzt. Den `call` Befehl könnte man tatsächlich mit einer `jmp` Anweisung ersetzten. Die Adresse des ersten Befehls einer Funktion kennt man ja nach dem Linken. Wenn die Funktion abgearbeitet ist muss man aber zurückspringen und zwar zu dem Maschinenbefehl der dem Funktionsaufruf folgt. Da die Funktion mehrfach aufgerufen werden kann ist diese Adresse aber nicht fix. Für jeden Funktionsaufruf muss man also eine Rücksprungadresse speichern. Stellt sich die Frage wo man die Rücksprungadresse speichern soll. Man kann einen festen Platz im Speicher ausmachen. Das geht gut solange nur eine Funktion aufgerufen wird. Ein zweiter Funktionsaufruf dürfte nur erfolgen, wenn man mit dem ersten Aufruf "fertig" ist, d.h. die Funktion abgearbeitet ist und zurückgesprungen wurde. Für jeden Funktionsaufruf muss man also einen neuen Platz für die Rücksprung Adresse festlegen. Wenn viele Funktionsaufrufe stattfinden, dann stapelt sich da was auf. Und da sind wir schon bei der Lösung. Die Rücksprungadressen werden einfach auf einem Stack gespeichert. Mit jedem Funktionsaufruf wird der Stack größer. Ganz oben auf dem Stack ist dann die Rücksprung Adresse für den letzten Funktionsaufruf. Darunter die für den vorletzten usw. :navigate: __up__ -> doc:index