Makroinstrukcje (MACRO, REPT, IRP, IRPC), dyrektywy (LOCAL
Transkrypt
Makroinstrukcje (MACRO, REPT, IRP, IRPC), dyrektywy (LOCAL
Grudzień, 2006 Makroinstrukcje (MACRO, REPT, IRP, IRPC), dyrektywy (LOCAL, PURGE, EXITM), operatory makroinstrukcji. Paweł Maziarz nr indeksu: 128954 Politechnika Wrocławska Wydział Informatyki i Zarządzania Makroinstrukcje mogą zastępować całe fragmenty kodu lub danych. Mogą też mieć też argumenty oraz zmienne lokalne. Użycie makroinstrukcji jest szybsze niż odpowiadającej jej funkcji, ponieważ makroinstrukcja nie używa rozkazów wywołania i powrotu. Asemblacja warunkowa zastosowana w makroinstrukcjach pozwala na ich optymalizację bez generowania dodatkowego kodu. Każde wywołanie makroinstrukcji jest zamieniane przez asembler na odpowiadający jej kod lub dane. Jeśli więc jest wywołana kilka razy, to potrzebuje więcej miejsca niż odpowiadająca jej funkcja – w zależności od wymagań więc rodzi się wybór – albo szybkość i używanie makroinstrukcji, albo ograniczona pamięć i używanie funkcji. Makroinstrukcje tworzy się wykorzystując dyrektywę MACRO, poprzedzając ją nazwą makroinstrukcji. Jeżeli makroinstrukcja ma przyjmować argumenty, podaje się ich nazwy za dyrektywą MACRO. Jeżeli zachodzi potrzeba usunięcia zdefiniowanej makroinstrukcji, używamy dyrektywy PURGE. Jeżeli z kolei chcemy pominąć niepotrzebną już część makroinstrukcji i zakończyć ją przed czasem, używamy dyrektywy EXITM. Załóżmy, że chcielibyśmy napisać makroinstrukcję PRINT, która wypiszę nam określony komunikat, mogła ona by wyglądać na przykład tak: PRINT MACRO komunikat mov ah,9 mov dx,OFFSET komunikat int 21h ENDM Każde pojawienie się wywołania makroinstrukcji powoduje zastąpienie jej generowanym przez nią kodem. Problem powstaje wówczas, gdy makroinstrukcja zawiera etykietę. Przy jej drugim wywołaniu asembler napotka taką samą etykietę, co spowoduje powstanie błędu. Z pomocą wtedy przychodzą zmienne lokalne definiowane dyrektywą LOCAL, która istnieją tylko w danym wywołaniu makroinstrukcji. Alternatywą do dyrektywy LOCAL jest użycie dyrektywy LOCALS, która zaznaczy etykiety lokalne podanymi przedrostkami. Poniżej prosty program obrazujący użycie wcześniejszego makra oraz dwóch nowych z wykorzystaniem LOCAL/LOCALS. .model small .stack PRINT MACRO komunikat mov ah,9 mov dx,OFFSET komunikat int 21h ENDM THREEPRINT1 MACRO komunikat LOCAL tloop mov cx,3 tloop: PRINT komunikat loop tloop ENDM LOCALS @@ THREEPRINT2 MACRO komunikat mov cx,3 @@tloop: PRINT komunikat loop @@tloop ENDM .data msg DB 'Witaj referacie!',13,10,'$' .code start: mov ax,@data mov ds,ax THREEPRINT1 msg THREEPRINT2 msg THREEPRINT1 msg THREEPRINT2 msg mov ah,4ch int 21h end start Popatrzmy na makroinstrukcje THREEPRINT1 i THREEPRINT2. W celu zrealizowania trzech przebiegów pętli wykorzystują etykiety oraz instrukcję loop. Istnieje alternatywna metoda z wykorzystaniem dyrektywy REPT. Blok instrukcji między REPT a kończącą go dyrektywą ENDM zostanie wykonana taką liczbę razy, jaka będzie wartość wyrażenia podana dyrektywie REPT i tak nowa wersja makroinstrukcji THREEPRINT2 może wyglądać następująco: THREEPRINT2 MACRO komunikat REPT 3 PRINT komunikat ENDM ENDM Podobną do pętli REPT jest pętla IRP. Różnica polega na tym, że w dyrektywie IRP można określić dla każdego obiegu pętli inną daną. Dane mogą być symbolami, łańcuchami lub liczbami. Np. by zrealizować sumę kilku dowolnych liczb, możemy posłużyć się kodem: xor bx,bx IRP skladnik, <13, 1, 7, 28, 12, 8> add bx,skladnik ENDM Kolejną z dyrektyw, które warto omówić, to dyrektywa IRPC, która jest bardzo podobna do wcześniejszej, z tą różnicą, że zamiast listy zmiennych, używa znaków łańcucha. Dla każdego z nich będzie powtórzony blok instrukcji. Znaki te zastąpią każde pojawienie się zmiennej w ciele pętli. Chcąc na przykład utworzyć listę zmiennych o nazwach bok_a, bok_b i bok_c, możemy użyć takiego kodu: IRPC litera, <abc> bok_&litera DW 0 %OUT Utworzono zmienna bok_&litera ENDM Mówiąc o makroinstrukcjach, nie sposób nie wspomnieć operatorach w nich występujących (niektóre nota bene w powyższych przykładach już wystąpiły), są to: & Wymuszenie podstawiania. Używane jest wewnątrz znaku cudzysłowu oraz, gdy argument znajduje się zaraz obok innego symbolu (jeden z przykładów powyżej). <> Literał tekstowy. Zapobiega próbom obliczania wartości łańcucha przed przekazaniem do makroinstrukcji. ! Występujący po nim znak nie jest traktowany jako operator (np. FOO 7, <Tekst ze znaczkiem większości !> w środku>). % Obliczenie wyrażenia i przekazanie jego wartości do makroinstrukcji (np. FOO %3+4). ;; Komentarz. Bibliografia: Gary Syck, Turbo Assembler Biblia Użytkownika, Warszawa 1994 http://google.com/