2013-08-02 7 views

Antwort

39

ist die komplette Tabelle der Register und deren Nutzung aus der Dokumentation [PDF Link]:

table from docs

r12, r13, r14, r15, rbx, rsp, rbp sind die Angerufene-gesicherten Register - sie In der Spalte "Bei Funktionsaufrufen beibehalten" muss ein "Ja" stehen.

+0

Upvoted. Vielen Dank! – boneheadgeek

+0

Was ist mit Fahnen? wie DF? – socketpair

+2

@socketpair: DF muss vor jedem Aufruf oder jeder Rückkehr nicht gesetzt sein, so dass das Aufwärtszählverhalten ohne "cld" angenommen werden kann. Zustandsflags (wie ZF) sind call-clobed. Ich vergesse genau, was die ABI-Dokumente über FP-Rundungsmodi und Denormals-are-zero sagen. Vielleicht etwas wie wenn eine Funktion sie modifiziert, muss sie den vorherigen Zustand speichern/wiederherstellen, bevor sie zurückkehrt, aber ** nimm mein Wort für den FP Teil nicht **. –

4

Der ABI legt fest, was eine standardkonforme Software erwarten darf. Es ist in erster Linie für Autoren von Compilern, Linkern und anderen Sprachverarbeitungssoftware geschrieben. Diese Autoren möchten, dass ihr Compiler Code erzeugt, der ordnungsgemäß mit Code funktioniert, der von demselben (oder einem anderen) Compiler kompiliert wird. Sie alle müssen einer Reihe von Regeln zustimmen: Wie werden formale Argumente an Funktionen vom Aufrufer an den Aufrufer übergeben, wie werden Funktionsrückgabewerte von Aufrufer an Aufrufer zurückgegeben, welche Register bleiben über die Aufrufgrenze erhalten/scratchen/undefiniert und so auf. Beispielsweise gibt eine Regel an, dass der generierte Assemblercode für eine Funktion den Wert eines beibehaltenen Registers speichern muss, bevor der Wert geändert wird, und dass der Code den gespeicherten Wert wiederherstellen muss, bevor er an seinen Aufrufer zurückgegeben wird. Für einen Scratch-Register ist der generierte Code nicht erforderlich, um den Registerwert zu speichern und wiederherzustellen; es kann dies tun, wenn es gewünscht wird, aber standardkonforme Software darf nicht von diesem Verhalten abhängig sein (wenn dies der Fall ist, ist es keine standardkonforme Software).

Wenn Sie Assembler-Code schreiben, sind Sie verantwortlich für das Spielen nach denselben Regeln (Sie spielen die Rolle des Compilers). Das heißt, wenn Ihr Code ein auf Abruf gespeichertes Register ändert, sind Sie dafür verantwortlich, Anweisungen einzufügen, die den ursprünglichen Registerwert speichern und wiederherstellen. Wenn Ihr Assembler-Code eine externe Funktion aufruft, muss Ihr Code Argumente in der standardkonformen Weise übergeben, und es kann davon abhängen, dass bei der Rückkehr des Angerufenen beibehaltene Registerwerte tatsächlich erhalten bleiben.

Die Regeln definieren, wie standardkonforme Software auskommen kann. Es ist jedoch völlig legal, Code zu schreiben (oder zu generieren), der nach diesen Regeln nicht spielt! Compiler tun dies ständig, weil sie wissen, dass die Regeln unter bestimmten Umständen nicht eingehalten werden müssen.

Betrachten wir zum Beispiel eine C-Funktion namens foo, die erklärt sich wie folgt:

static foo(int x); 

zur Compile-Zeit, der Compiler ist zu 100% sicher, dass diese Funktion nur von anderen Code in der Datei aufgerufen werden (s) es wird gerade kompiliert. Die Funktion foo kann aufgrund der Definition dessen, was es bedeutet, statisch zu sein, nicht anders genannt werden. Da der Compiler alle Compiler des Aufrufs foo zur Kompilierzeit kennt, kann der Compiler die gewünschte Aufrufsequenz verwenden (bis hin zu einem Aufruf überhaupt), dh den Code für foo in die Aufrufer von foo einbinden .

Als Autor von Assembler-Code können Sie dies auch tun.Das heißt, Sie können eine "private Vereinbarung" zwischen zwei oder mehr Routinen implementieren, solange diese Vereinbarung nicht die Erwartungen einer standardkonformen Software stört oder verletzt.

Verwandte Themen