Sdílet prostřednictvím


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

Specifické pro Microsoft

Obecně byste neměli předpokládat, že při zahájení bloku bude mít registr danou __asm hodnotu. Nezaručují se zachování hodnot registru napříč samostatnými __asm bloky. Pokud ukončíte blok vloženého kódu a zahájíte další, nemůžete se spolehnout na registry v druhém bloku, aby si zachovaly 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žíváte __fastcall konvenci volání, kompilátor předá argumenty funkce v registrech místo v zásobníku. To může způsobit problémy s funkcemi s __asm bloky, protože funkce nemá způsob, jak zjistit, který parametr je v jakém registru. Pokud funkce přijme 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é s __fastcall.

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

Při psaní __asm jazyka sestavení ve funkcích C/C++ nemusíte zachovat registry EAX, EBX, ECX, EDX, ESI nebo EDI. Například v POWER2. Příklad jazyka C při psaní funkcí s vloženým sestavenímpower2 funkce nezachovává hodnotu v registru EAX. Použití těchto registrů však ovlivní kvalitu kódu, protože alokátor registru je nemůže použít k ukládání hodnot napříč __asm bloky. Kromě toho pomocí EBX, ESI nebo EDI vloženého kódu sestavení vynutíte kompilátor uložit a obnovit tyto registry ve funkci prologue a epilogue.

Pro rozsah __asm bloku byste měli zachovat další používané registry (například DS, SS, SP, BP a příznaky). Registry ESP a EBP byste měli zachovat, pokud nemáte nějaký důvod je změnit (například pro přepínání zásobníků). Viz také optimalizace vložené sestavení.

Některé typy SSE vyžadují zarovnání zásobníku s osmi bajty a vynucení kompilátoru k generování kódu dynamického zarovnání zásobníku. Aby bylo možné po zarovnání získat přístup k místním proměnným i parametrům funkce, kompilátor udržuje dva ukazatele rámce. Pokud kompilátor vynechá ukazatel rámce (FPO), použije EBP a ESP. Pokud kompilátor neprovádí FPO, použije EBX a EBP. Pokud chcete zajistit správné spuštění kódu, neupravujte v asm kódu EBX, pokud funkce vyžaduje dynamické zarovnání zásobníku, protože by mohlo upravit ukazatel rámce. Buď přesuňte 8bajtů zarovnané typy mimo funkci, nebo nepoužívejte EBX.

Poznámka

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

END Microsoft Specific

Viz také

Vkládaný assembler