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