Zagadnienia dotyczące pisania kodu prologu/epilogu
Specyficzne dla firmy Microsoft
Przed napisaniem własnej sekwencji kodu prologu i epilogu ważnym jest, aby zrozumieć układanie ramek stosu.Warto także dowiedzieć się, jak używać symbolu __LOCAL_SIZE.
Układ ramki stosu
W tym przykładzie pokazano standardowy kod prologu, który może pojawić się w 32 bitowej funkcji:
push ebp ; Save ebp
mov ebp, esp ; Set stack frame pointer
sub esp, localbytes ; Allocate space for locals
push <registers> ; Save registers
Zmienna localbytes reprezentuje liczbę bajtów potrzebnych na stosie dla zmiennych lokalnych a zmienna <registers> jest symbolem zastępczym reprezentującym listę rejestrów, które mają być zapisane na stosie.Po umieszczeniu rejestrów na stosie, można tam umieścić inne odpowiednie dane.Poniżej przedstawiono odpowiadający kod epilogu:
pop <registers> ; Restore registers
mov esp, ebp ; Restore stack pointer
pop ebp ; Restore ebp
ret ; Return from function
Stos zawsze powiększa się w dół (od najwyższego do najniższego adresu pamięci).Podstawowy wskaźnik (ebp) wskazuje na umieszczoną wartość ebp.Obszar lokalny rozpoczyna się od ebp-4.Aby uzyskać dostęp do zmiennych lokalnych, należy obliczyć przesunięcie z ebp przez odjęcie odpowiedniej wartości od ebp.
__LOCAL_SIZE
Kompilator dostarcza symbolu __LOCAL_SIZE, do użytku w bloku asemblera wbudowanego w kodzie prologu funkcji.Ten symbol jest używany do alokowania miejsca dla zmiennych lokalnych na ramkach stosu w niestandardowym kodzie prologu.
Kompilator określa wartość __LOCAL_SIZE.Jej wartością jest całkowita liczba bajtów wszystkich zmiennych lokalnych zdefiniowanych przez użytkownika i zmiennych tymczasowych wygenerowanych przez kompilator.__LOCAL_SIZE może być używana tylko jako bezpośredni argument; Nie może być użyta w wyrażeniu.Nie wolno zmieniać lub ponownie definiować wartości tego symbolu.Na przykład:
mov eax, __LOCAL_SIZE ;Immediate operand--Okay
mov eax, [ebp - __LOCAL_SIZE] ;Error
Poniższy przykład nagiej funkcji zawiera niestandardowe sekwencje prologu i epilogu, i używa symbolu __LOCAL_SIZE w sekwencji prologu:
// 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
}
}