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/