Důležité informace k zápisu kódu prologu/epilogu
Specifické pro Microsoft
Před psaním vlastních sekvencí kódu prologu a epilogu je zapotřebí porozumět rozložení rámce zásobníku.Také je užitečné vědět, jak používat konstantu __LOCAL_SIZE.
Rozložení rámce zásobníku
Tento příklad ukazuje standardní kód prologu, který se může vyskytnout v 32bitové funkci:
push ebp ; Save ebp
mov ebp, esp ; Set stack frame pointer
sub esp, localbytes ; Allocate space for locals
push <registers> ; Save registers
Proměnná localbytes představuje počet bajtů zásobníku potřebných pro místní proměnné a proměnná <registers> je zástupný symbol představující seznam registrů, které mají být uloženy do zásobníku.Po vložení registrů lze do zásobníku uložit libovolná jiná vhodná data.Následující výpis ukazuje odpovídající kód epilogu:
pop <registers> ; Restore registers
mov esp, ebp ; Restore stack pointer
pop ebp ; Restore ebp
ret ; Return from function
Zásobník roste vždy směrem dolů (od vysokých po nízké adresy paměti).Základní ukazatel (ebp) ukazuje na vloženou hodnotu proměnné ebp.Lokální oblast začíná na ebp-4.Chcete-li přistoupit k místním proměnným, vypočítejte posun vůči adrese ebp odečtením příslušné hodnoty od adresy ebp.
__LOCAL_SIZE
Kompilátor poskytuje konstantu __LOCAL_SIZE, kterou lze použít ve vloženém bloku assembleru daného kódu prologu funkce.Tato konstanta se používá k přidělení místa pro místní proměnné v rámci zásobníku ve vlastním kódu prologu.
Hodnotu konstanty __LOCAL_SIZE určuje kompilátor.Hodnotou je celkový počet bajtů všech uživatelem definovaných místních a kompilátorem generovaných dočasných proměnných.Konstantu __LOCAL_SIZE lze použít pouze jako přímý operand. Nelze ji použít ve výrazu.Hodnota této konstanty nesmí být v kódu měněna nebo předefinována.Příklad:
mov eax, __LOCAL_SIZE ;Immediate operand--Okay
mov eax, [ebp - __LOCAL_SIZE] ;Error
Následující příklad neviditelné funkce obsahující vlastní sekvence prologu a epilogu používá v sekvenci prologu konstantu __LOCAL_SIZE:
// 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
}
}