KURS ASEMBLER'A
1.Wprowadzenie
Asembler jest językiem niskiego poziomu w odróżnieniu od pascala czy c. W praktyce oznacza to, że programista wiele operacji musi przeprowadzać sam, nie zrobi tego nikt za niego. Pozatym ma bliższy dostęp bezpośrednio do sprzętu, pamięci itp. Może obsługiwać klawiaturę, mysz, kartę graficzną swoimi funkcjami i przerwaniami. Ale aby to mógł robić musi umieć programować w tym niezrozumiałym na pierwszy rzut oka języku. To co musisz posiadać, aby programować w tym języku to: jakiś edytor tekstu (edti czy notepad), kompilator asemblera (polecam TASM`a - Turbo Asembler i MASM`a - Makro Asembler) pierwszy z nich jest firmy Borland i jest dołączony do pascala, drugi zaś firmy Microsoft oraz linkera (np. TLINK). To wszystko! ;-)
2.Podstawy i składnia
Teraz poznacie szkielet programu COM w czystym asemblerze oraz szkielet wstawki asemblerowej w pascalu. Otóż pliku COM są plikami, które zajmują max 64 KB czyli jeden segment, co oznacza, że zarówno kod programu i dane muszą znaleźć się w jednym segmencie. Teraz wydaje Ci się, że 64 KB to nic, ale przekonasz się, że asembler jest językiem o bardzo zwięzłym kodzie, co w efekcie daje mały rozmiar pliku. Tak wygląda szkielet programu COM:
.MODEL tiny ;ustalamy model pamięci na drobny
.STACK 100h ;ustalamy rozmiar stosu na 100h
.DATE ;możemy ustalić miejsce na deklaracje zmiennych
deklaracje zmiennych
.CODE ;tu rozpoczyna się właściwy kod programu
org 100h ;program rozpoczyna się od CS:0100H - kolejna cecha COM`ów
treść programu
mov ax, 4C00h ;funkcja kończenia procesu
int 21h ;wywołanie funkcji poprzez wywołanie przerwania 21h
END ;koniec kodu programu
Pewnie teraz czujecie się lepiej. Kompilujecie program a tu powstał EXE i jesteście w kropce, nie martwcie się, użyjcie programu np. EXE2BIN lub EXE2COM i po problemie. Myslę, że teraz przejdziemy do wstawki, a potem wyjaśnimy podstawowe mnemoniki.
Tak wygląda wstawka asemblera w pascalu:
asm
..... treśc
..... treść
end;
I już koniec, tutaj kompilator odwala za nas całą robotę model, stack itp.Teraz zapoznamy się z podstawowymi rejestrami i znacznikami:
Rejestry:
AX, BX, CX, DX - 16 bitowe rejestry ogólnego przeznaczenia, dzielą się każdy na dwa 8 bitowe xH i xL, gdzie x to pierwsza litera rejestru 16 bitiwego. AX dzieli się na AH i AL itp. AX najczęściej wykorzystuje się przy operacjach arytmetycznych, BX przy adresowaniu pamięci, CX przy pętlach i powtórzeniach.
CS, DS, SS, ES - 16 bitowe rejestry segmentowe, CS-segment kodu (CS:CODE), DS-segment danych (DS:DATE), SS-segment stosu, ES-segment dodatkowy.
DI, SI - 16 bitowe rejestry indeksujące pamięć
SP - wzkaźnik stosu
Znaczniki:
S - znacznik znaku
Z - znacznik zera
C - znacznik przeniesienia
O - znacznik nadmiaru
I - znacznik dostępności przerwań
D - znacznik kierunku
P - znacznik parzystości
W tej chwili powinieneś poznać podstawowe mnemoniki i ich znaczenie:
mov - podstawowy mnemonik służący do ładowania wartości do rejestrów, rejestrów do rejestrów itp. np. mov ax, 150h oznacza załaduj do ax liczbę 150h . Jednak nie każdy rejestr może być ładowany wartością natychmiastową np. mov ds, 150h należy posłużyć się wtedy innym rejestrem np. mov ax, 150h mov ds, ax . Czyli składnia mov a, b (a-miejsce docelowe, b-wartość do załadowania).
push - odłóż na wierzchołek stosu, odkłada się rejestry, wartości itp. z tym, że odłożenie wartości a, a potem b spowoduje zakrycie wartości a przez b. Wynika z tego to, że najpierw musimy zdjąc wartość b, a potem a np. push ax push 150h . Składnia push a (a-coś do odłożenia).
pop - pobierz z wierzchołka stosu, pobiera się to co się odłoży np. pop ax pop liczba - powoduje pobrania wartości z wierzchołka i wpisaniu jej do miejsca docolowego. Składnia: pop a (a - miejsce docelowe pobrania).
add - dodaj wartość drugiego argumentu do pierwszego add ax, 5 - dodaj 5 do ax. Składnia: add a, b.
sub - odejmij wartość drugiego argumentu do pierwszego sub ax, 5 - odejmij 5 od ax. Składnia sub a, b.
mul - przemnóż wartość rejestru ax przez zmienną mul a - pomnóż ax i a. Składnia: mov ax, zmienna ... mul a
div - podziel wartość rejestru ax przez zmienną, w rejestrze al jest wynik całkowity, a w ah reszta z dzielenia. jeżeli dzielimy przez zero nastąpi wywołanie przerwania. Składnia: mov ax, zmienna ... div a
not - negacja logiczna, zamiana bitów na przeciwne np. a=1010 not a da wynik w a 0101. Składnia: not a
and - iloczyn logiczny, wykonuje go na dwóch bitach z każdej zmiennej np. a=1010 b=1110 and a, b da wynik w a=1010. Składnia: and a, b
test - jw. z tym, że nie zapisuje wyniku, tylko uwzględnia znacznkiki. Składnia: test a, b
or - suma logiczna, wykonuje się na dwóch bitach z każdej zmiennej np a=1110 b=1000 or a, b da wynik w a=1110. Składnia: or a, b
xor - różnica arytmetyczna, wykonuje się na dwóch bitach z każdej zminnej np. a=1001 b=1011 xor a, b wynik w a=0110. Składnia: xor a, b
jmp - bezwarunkowy skok pod adres wzkazany przez zmienną(etykietę) np. jmp malpa skok do etykiety malpa (etykieta musi kończyć się ':'). Składnia: jmp a
je/jz - skok gdy Z=1 .Składnia: je malpa
jne/jnz - skok gdy Z=0 Składnia: jw
js - skok gdy S=1
jns - skok gdy S=0
jc - skok gdy C=1
jnc - skok gdy C=0
jo - skok gdy O=1
jno - skok gdy O=0
loop - skok do początku pętli(etykiety), ilość wykonania się pętli zapisuje się do rejestru cx np, mov cx, 100 @petla: ... loop @petla - spowoduje wykonanie się 100 razy tej pętli. Składnia mov cx, ile @etyk: ... loop @etyk
call - wywołuje procedurę z możliwością powrotu do miejsca wywołania np. call otul - wywołuje procedurę otul i zapisuje na stos wartości miejsca powrotu, w procedurze mnemonik ret zdejmuje je i powraca, tak więc jeżli zostawicie coś na stosie spowoduje to błąd. Składnia: call a
ret - zdejmuje ze stosu miejsce powrotu z procedury. Składnia: ret
nop - nie rób nic (pusta instrukcja - może być wykorzystywana do opóźnień). Składnia: nop
in - przesyłanie danych z portu do rejestru lub zmiennej np. mov dx, 21h in al, dx - spowoduje przesłanie bajtu do al z portu 21h, natomist in ax, dx - przesłanie słowa. Składnia in a, b
out - przesyłanie danych do portu z rejestru lub zmiennej np. mov dx, 21h out dx, al - spowoduje przesłanie bajtu z al do portu 21h, a ax słowa. Składnia out a, b
cmp - porównanie wartości a i b, nie umieszcza wyniku, ale zmienia znaczniki. Porównanie nastepuje poprzez odjęcie od a b. Składnia cmp a, b
clc - ustawienie znacznika C na 0 (C=0)
stc - C=1
cld - D=0
std - D=1
cli - I=0
sti - I=1
int - wywołuje przerwanie np. int 21h - wywołuje przerwanie DOS`a. Składnia: int a
movsb - kopiuje bajt spod adresu DS:[SI] do bajtu spod adresu ES:[DI] i zwiększa lub zmniejsza SI i DI w zależności od znacznika D
Wystarczy już tych mnemoników, resztę można znaleźć w kursie lub w literaturze.
3.Przykłady
Teraz przechodzimy do konkretów, przedstawię dwa przykłady, jeden w czystym asm, a drugi jako wstawkę.
Program wyświetlający nieśmiertelny napis 'Hello World!':
.MODEL tiny
.STACK 100h
.CODE
org 100h
tekst db 'Hello World!','$' ;deklaruję zmienną tekst typu bajt
mov ax, seg tekst ;ładuje do ax adres segmentu zmiennej tekst
mov ds, ax
mov ah, 09h ;ładuje do ah numer funkcji do wyświetlania tekstu (przerwanie 21h)
mov dx, offset tekst ;ładuje do dx offset zmiennej tekst
int 21h
mov ax, 4C00h ;funkcja kończenia procesu
int 21h
END
Program we wstawce wyświetlający znak:
asm
mov ah, 02h
mov dl, 1
int 21h
end;