Programowanie hybrydowe C (C++) - assembler MS Visual Studio Inline Assembler
Wprowadzenie Możliwość wprowadzania kodu asemblerowego bezpośrednio w kodzie źródłowym w języku C lub C++ Nie wymagany MASM ani dodatkowa faza linkowania Dedykowany dla procesorów x86 Brak przenoszalności programów na inne platformy, w tym także na x64
Podstawy W kodzie asemblerowym można wykorzystać dowolną zmienną lub nazwę funkcji języka C (C++), która występuje w zasięgu tego kodu Kod asemblerowy musi być poprzedzony słowem kluczowym _asm może ono występować przed każdą instrukcją asemblera z osobna może wystąpić przed blokiem instrukcji asemblera (muszą one wystąpić w nawiasach klamrowych)
Przykład 1 // asm_overview.cpp // processor: x86 void declspec(naked) main() { // Naked functions must provide their own prolog... asm { push ebp mov ebp, esp sub esp, LOCAL_SIZE } //... and epilog asm { pop ebp ret } }
Przykład II asm push ebp asm mov ebp, esp asm sub esp, LOCAL_SIZE
Zalety i wady stosowania inline asemblera Zalety: możliwość pisania funkcji w asemblerze punktowa optymalizacja krytycznych sekcji kodu możliwość bezpośredniego dostępu do sprzętu możliwość napisania własnego prologu i epilogu dla gołych funkcji Wady: ograniczenie zastosowań do procesorów x86 brak możliwości zastosowania dyrektyw MASM-a
Składnia asm instrukcja_asemblera [;] asm {blok _instrukcji_asemblera }[;] Kończenie instrukcji średnikiem jest opcjonalne Uwaga na podwójne podkreślenie, chociaż ze względu na wsteczną kompatybilność działa również _asm (z pojedynczym podkreśleniem), nie działa natomiast asm (bez podkreśleń) ze standardu C++ (chociaż kompilator w tym przypadku nie zgłasza błędu, to kod wynikowy nie zostanie wygenerowany)
Zbiór instrukcji Wszystkie do modelu Pentium 4 i AMD Athlon włącznie
Wyrażenia MASM-a Wszystkie tak samo jak w MASM-ie
Dyrektywy związane z danymi Blok instrukcji asemblerowych może korzystać z definicji danych języka C (C++) Nie można definiować danych przy użyciu dyrektyw i operatorów MASM-a Niedozwolone jest stosowanie: dyrektyw: DB, DW, DD, DQ, DT, DF operatorów: DUP i THIS dyrektyw STRUC, RECORD, WIDTH, MASK
Dyrektywy EVEN i ALIGN Dopuszczalne Służą wyrównywaniu naturalnemu pamięci kodu przez wstawianie instrukcji NOP wtedy, gdy jest to wskazane Przyspiesza działanie fazy pobrania instrukcji w procesorze
Makrodyrektywy MASM-a Zabronione jest stosowanie: makrodyrektyw: MACRO, REPT,IRC, IRP, ENDM makro operatorów: <>,!, &, %, TYPE W bloku asm można używać dyrektyw preprocesora C
Stosowanie elementów języka C/C++ w blokach asm Dopuszczalne jest użycie wewnątrz bloku asm następujących elementów języka C/C++: symboli etykiety, nazwy zmiennych, nazwy funkcji stałych w tym stałych symbolicznych oraz elementów typu wyliczeniowego (enum) makr i dyrektyw preprocesora komentarzy (zarówno /* */, jak i // nazw typów nazw typów zadeklarowanych przez typedef (używanych w połączeniu z operatorami PTR i TYPE lub przy definiowaniu składowych struktury lub unii) stałe szesnastkowe w notacji C/C++ (0x100)lub asemblerowej (100h) stałe ósemkowe (wymagane wiodące zero np. 0765)
Używanie operatorów W bloku asm: nie można korzystać z operatorów języka C/C++ można korzystać z operatorów, które występują w obydwu językach, ale będą one traktowane jak operatory asemblera
Używanie operatorów - przykład Niepoprawne int array[10]; asm mov array[6], bx ; zawartość BX zapisana pod adresem array+6 (brak skalowania) array[6] = 0; /* zapisanie 0 pod adresem array+24 (skalowanie) */ Poprawne asm mov array[6 * TYPE int], 0 ; zapisanie 0 pod adresem array+24 array[6] = 0; /* zapisanie 0 pod adresem array+24 */
Używanie symboli W bloku asm można używać symboli języka C/C++ (nazwy zmiennych, etykiety itp.), które są w zasięgu tego bloku Ograniczenia: w pojedynczej instrukcji asemblera może wystąpić co najwyżej jeden symbol język C/C++ (wyjątek stanowi użycie symboli w połączeniu z LENGTH, TYPE, SIZE) funkcje, do których następuje odwołanie w instrukcji asemblerowej muszą być wcześniej zadeklarowane symbole C/C++ używane w bloku asm nie mogą mieć takiej samej nazwy, jak zastrzeżone słowa asemblera znaczniki struktury lub unii nie są rozpoznawane w blokach asm
Używanie danych Można odwołać się przez nazwę zmiennej Przykład: asm mov eax, var Dostęp do pól unii lub struktur: możliwy za pośrednictwem nazwy tego pola, jeśli jest unikalne jeśli nie - konieczny zapis kropkowy Dostęp do obiektów: pola na podobnej zasadzie metody zabronione