Kurs programowania w asemblerze
Procedury i marka
Deklarowanie procedur
Asembler, jak i inne języki programowania, daje nam możliwość tworzenia własnych procedur. Do tego celu używa się dyrektywy PROC poprzedzonej nazwą naszej procedury. Ogólna budowa jest następująca:
Nazwa PROC <treść procedury> RET Nazwa ENDP
Instrukcja RET powoduje powrót do miejsca, z którego procedura została wywołana. Do wywołania procedury używa się instrukcji CALL. Parametrem CALL może być również bezpośredni adres. Używa się tego, gdy np. chcemy wywołać odpowiednią procedurę w zależności od wartości rejestru BX. Adresy tych procedur, lub ich nazwy podajemy w tablicy, np:
tablica_procedury DD proc0, proc1, proc2 ; bx zawiera wartość od 0 do 2 mov si,bx ; zachowaj BX shl si,1 ; policz przesunięcie shl si,1 ; adresu w tablicy call tablica_procedur[si] ; deklaracja procedury procka PROC <treść> RET ENDP ...
By procesor wiedział, gdzie ma później wrócić podczas wywoływania instrukcji CALL na stosie zostanie położony: w przypadku procedury NEAR rejestr IP. Później wykonany zostanie skok, a po napotkaniu RET następuje zdjęcie ze stosu IP, czyli powrót do instrukcji CALL. W przypadku procedury FAR na stosie zostanie położony rejestr CS i IP, dalsze działanie jest takie same jak przy procedurach NEAR.
Deklarowanie makroinstrukcji
Makroinstrukcja jest to zbiór instrukcji asemblera oznaczonych jedną nazwą. Jeśli więc jakąś sekwencję wykonujemy w programie wiele razy możemy stworzyć odpowiednie makro. Jest to znacznie szybsze od tworzenia procedur, jednak stosowanie makroinstrukcji powoduje zwiększenie objętości programu. Jak już wiemy, procedury, są to podprogramy, do których wykonujemy skok. Skok jest wolny. Makro jest to sekwencja, która zostanie wstawiona we wskazane miejsce. Nie ma wówczas straty czasu na skoki, jednak objętość rośnie.
Makroinstrukcję deklarujemy w następujący sposób:
nazwa MACRO lista_parametrów <treść> ENDM
Tak może wyglądać przykładowa makroinstrukcja:
Print MACRO tekst PUSHA MOV AH,09H PUSH CS POP DS LEA DX,tekst INT 21H POPA ENDM
Teraz program może wyglądać tak:
Print Napis1 Print Napis2 ... Napis1 DB "BY BINBOY",13,120,'$' Napis2 DB "www.howtocode.pl",13,10,'$'
Podczas pisania makroinstrukcji zachodzi czasami konieczność sprawdzenia, czy jakiś argument został podany, czy też nie. Do tego celu służą dyrektywy warunkowe, i tak:
IFB- powoduje wstawienie do programu instrukcji znajdujących się międzyIFBaENDIFtylko wtedy, gdy parametr podany doIFBjest pusty.IFNB- powoduje wstawienie do programu kodu, gdy parametr nie jest pustyEXITM- powoduje zakończenie makroinstrukcji
Przykładowa makroinstrukcja DELAY
Delay MACRO ile
PUSH CX
IFB ile
MOV CX,1000
ENDIF
IFNB ile
MOV CX,ile
ENDIF
WAI:
LOOP WAI
POP CX
ENDM
Często używane makroinstrukcje wygodnie jest przechowywać w osobnym pliku, dołączanym do programu za pomocą dyrektywy include, np:
include graph.asm
