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