Udostępnij za pośrednictwem


Korzystanie z rejestrów i zachowywanie ich w asemblerze wbudowanym

Specyficzne dla firmy Microsoft

Ogólnie rzecz biorąc, nie należy zakładać, że rejestr będzie miał daną wartość po rozpoczęciu __asm bloku. Nie ma gwarancji, że wartości rejestru zostaną zachowane w oddzielnych __asm blokach. Jeśli zakończysz blok kodu wbudowanego i rozpoczniesz inny, nie możesz polegać na rejestrach w drugim bloku, aby zachować ich wartości z pierwszego bloku. Blok __asm dziedziczy wszystkie wartości rejestru wynikające z normalnego przepływu sterowania.

Jeśli używasz __fastcall konwencji wywoływania, kompilator przekazuje argumenty funkcji w rejestrach zamiast na stosie. Może to powodować problemy w funkcjach z blokami, __asm ponieważ funkcja nie ma sposobu na określenie parametru, w którym rejestrze. Jeśli funkcja otrzyma parametr w programie EAX i natychmiast zapisze coś innego w programie EAX, oryginalny parametr zostanie utracony. Ponadto należy zachować rejestr ECX w dowolnej funkcji zadeklarowanej za pomocą __fastcallpolecenia .

Aby uniknąć takich konfliktów rejestrów, nie należy używać __fastcall konwencji dla funkcji, które zawierają __asm blok. Jeśli określisz konwencję __fastcall globalnie z opcją /Gr kompilatora, zadeklaruj każdą funkcję zawierającą blok z opcją __asm __cdecl lub __stdcall. (Atrybut __cdecl nakazuje kompilatorowi użycie konwencji wywoływania języka C dla tej funkcji). Jeśli nie kompilujesz z /Gr, unikaj deklarowania funkcji za pomocą atrybutu __fastcall .

Podczas __asm pisania języka zestawu w funkcjach C/C++ nie trzeba zachowywać rejestrów EAX, EBX, ECX, EDX, ESI lub EDI. Na przykład w usłudze POWER2. Przykład języka C w artykule Writing Functions with Inline Assembly (power2Pisanie funkcji za pomocą zestawu wbudowanego) funkcja nie zachowuje wartości w rejestrze EAX. Jednak użycie tych rejestrów będzie miało wpływ na jakość kodu, ponieważ alokator rejestru nie może ich używać do przechowywania wartości w __asm blokach. Ponadto przy użyciu EBX, ESI lub EDI w wbudowanym kodzie zestawu wymusisz, aby kompilator zapisywał i przywracał te rejestry w prologu funkcji i epilogu.

Należy zachować inne rejestry używane (takie jak DS, SS, SP, BP i rejestry flag) dla zakresu __asm bloku. Należy zachować rejestry ESP i EBP, chyba że masz jakiś powód, aby je zmienić (na przykład do przełączania stosów). Zobacz również Optymalizowanie wbudowanego zestawu.

Niektóre typy SSE wymagają wyrównania stosu ośmiu bajtów, co zmusza kompilator do emitowania dynamicznego kodu wyrównania stosu. Aby uzyskać dostęp zarówno do zmiennych lokalnych, jak i parametrów funkcji po wyrównaniu, kompilator zachowuje dwa wskaźniki ramki. Jeśli kompilator wykonuje pominięcie wskaźnika ramki (FPO), będzie używać EBP i ESP. Jeśli kompilator nie wykonuje obiektu FPO, będzie używać EBX i EBP. Aby upewnić się, że kod działa poprawnie, nie należy modyfikować ebX w kodzie asm, jeśli funkcja wymaga dynamicznego wyrównania stosu, ponieważ może modyfikować wskaźnik ramki. Przenieś typy wyrównane z ośmiu bajtów z funkcji lub unikaj korzystania z EBX.

Uwaga

Jeśli wbudowany kod zestawu zmienia flagę kierunku przy użyciu instrukcji STD lub CLD, musisz przywrócić flagę do oryginalnej wartości.

END Microsoft Specific

Zobacz też

Wbudowany asembler