Überlegungen zum Schreiben von Prolog- und Epilogcode
Microsoft-spezifisch
Vor dem Schreiben eigener Prolog- und Epilogcodesequenzen ist es wichtig, zu verstehen, wie der Stapelrahmen festgelegt ist. Es ist auch hilfreich zu wissen, wie das __LOCAL_SIZE-Symbol verwendet werden kann.
Stapelrahmenlayout
In diesem Beispiel wird der Standardprologcode veranschaulicht, der in einer 32-Bit-Funktion enthalten sein kann:
push ebp ; Save ebp
mov ebp, esp ; Set stack frame pointer
sub esp, localbytes ; Allocate space for locals
push <registers> ; Save registers
Die localbytes-Variable gibt die Anzahl von Bytes an, die auf dem Stapel für lokale Variablen erforderlich sind. Die <registers>-Variable ist ein Platzhalter, der die Liste der Register darstellt, die auf dem Stapel gespeichert werden sollen. Nach dem Verschieben der Register können Sie alle weiteren entsprechenden Daten auf dem Stapel platzieren. Im Folgenden wird der entsprechende Epilogcode dargestellt:
pop <registers> ; Restore registers
mov esp, ebp ; Restore stack pointer
pop ebp ; Restore ebp
ret ; Return from function
Der Stapel wächst immer nach unten (von hohen zu niedrigen Speicheradressen). Der Basiszeiger (ebp) zeigt auf den abgelegten ebp-Wert. Der Gültigkeitsbereich der lokalen Variablen beginnt bei ebp-4. Um auf lokale Variablen zuzugreifen, berechnen Sie einen Offset von ebp, indem Sie den entsprechenden Wert von ebp subtrahieren.
__LOCAL_SIZE
Der Compiler stellt das Symbol __LOCAL_SIZE für die Verwendung im Inlineassemblerblock des Funktionsprologcodes bereit. Mit diesem Symbol wird Speicherplatz für lokale Variablen im Stapelrahmen im benutzerdefinierten Prologcode zugeordnet.
Der Compiler bestimmt den Wert von __LOCAL_SIZE. Sein Wert ist die Gesamtzahl von Bytes aller benutzerdefinierten lokalen Variablen und der vom Compiler generierten temporären Variablen. __LOCAL_SIZE kann nur als unmittelbarer Operand verwendet werden. Er kann nicht in einem Ausdruck verwendet werden. Sie dürfen den Wert dieses Symbols nicht ändern oder neu definieren. Beispiel:
mov eax, __LOCAL_SIZE ;Immediate operand--Okay
mov eax, [ebp - __LOCAL_SIZE] ;Error
Im folgenden Beispiel für eine naked-Funktion, die benutzerdefinierte Prolog- und Epilogsequenzen enthält, wird das __LOCAL_SIZE-Symbol in der Prologsequenz verwendet:
// the__local_size_symbol.cpp
// processor: x86
__declspec ( naked ) int main() {
int i;
int j;
__asm { /* prolog */
push ebp
mov ebp, esp
sub esp, __LOCAL_SIZE
}
/* Function body */
__asm { /* epilog */
mov esp, ebp
pop ebp
ret
}
}