Použití a zachování registrů v sestavení inline assemblerem

Specifické pro Microsoft

Obecně byste neměli předpokládat, že registr bude mít při zahájení bloku danou __asm hodnotu. Nezaručuje se, že hodnoty registru budou zachovány napříč samostatnými __asm bloky. Pokud ukončíte blok v řádku kódu a zahájíte další, nemůžete spoléhat na registry v druhém bloku, abyste zachovali své hodnoty z prvního bloku. Blok __asm dědí všechny hodnoty registru, které jsou výsledkem normálního toku řízení.

Pokud použijete __fastcall konvenci volání, kompilátor předá argumenty funkce v registrech místo v zásobníku. To může ve funkcích způsobovat problémy s bloky, protože funkce nemá žádný způsob, jak zjistit, ve kterém parametru __asm je registr. Pokud funkce obdrží parametr v EAX a okamžitě uloží něco jiného v EAX, původní parametr se ztratí. Kromě toho je nutné zachovat registr ECX v jakékoli funkci deklarované pomocí __fastcall .

Abyste se takovým konfliktům registru vyhnuli, nepoužívejte __fastcall konvenci pro funkce, které obsahují __asm blok. Pokud zadáte __fastcall konvenci globálně pomocí možnosti kompilátoru /Gr, deklarujte každou funkci obsahující __asm blok pomocí nebo __cdecl__stdcall . (Atribut říká kompilátoru, aby pro tuto funkci používá __cdecl konvenci volání jazyka C.) Pokud nesčítáte s /Gr, vyhněte se deklaraci funkce s __fastcall atributem .

Při psaní jazyka sestavení ve funkcích C/C++ není nutné zachovávat registry __asm EAX, EBX, ECX, EDX, ESI nebo EDI. Například v POWER2. Příklad jazyka C v zápisu funkcí s vloženým sestavenímnezachová funkce hodnotu v registru EAX. Použití těchto registrů ale ovlivní kvalitu kódu, protože je alokátor registru nemůže použít k ukládání hodnot napříč __asm bloky. Kromě toho při použití EBX, ESI nebo EDI ve vloženém kódu sestavení vynutíte, aby kompilátor tyto registry ukládal a obnovuje ve funkcích prolo zachytávaného a epilogu.

Ostatní registry, které používáte (například DS, SS, SP, BP a registry příznaků), byste měli zachovat pro rozsah __asm bloku. Měli byste zachovat registry ESP a EBP, pokud nemáte nějaký důvod je změnit (například přepnout zásobníky). Další informace najdete v tématu Optimalizace v řádku sestavení.

Některé typy SSE vyžadují zarovnání zásobníku o 8 bytech, takže kompilátor musí generovat dynamický kód pro zarovnání zásobníku. Aby bylo možné získat přístup k místním proměnným i parametrům funkce po zarovnání, udržuje kompilátor dva ukazatele rámce. Pokud kompilátor provede vynechání ukazatele rámce (FPO), použije EBP a ESP. Pokud kompilátor neprovádí objekt FPO, použije EBX a EBP. Pokud chcete zajistit správné spuštění kódu, neupravujte EBX v kódu asm, pokud funkce vyžaduje dynamické zarovnání zásobníku, protože by mohla upravit ukazatel rámce. Buď přesuňte zarovnané osmimístné typy z funkce, nebo se vyhněte použití EBX.

Poznámka

Pokud vložený kód sestavení změní příznak směru pomocí instrukcí STD nebo CLD, musíte příznak obnovit na původní hodnotu.

END Microsoft Specific

Viz také

Vložený assembler