Podstawy asemblera



Do tworzenia programu źródłowego potrzebne są instrukcje i dyrektywy, których znaczenie trzeba doskonale rozumieć. Musimy też zręcznie poruszać się w środowisku, w którym "zanurzany" jest źródłowy program asemblerowy. W tym środowisku, każda instrukcja programowa ma swoje własne pole.

Pole etykiety Pole operacji

Pole operandów

Pole komentarza
Start: MOV CX, Zliczaj ;kopiuj bajt do CX
Powtarzaj: DEC CX ;zmniejszaj CX o 1
    STD  
Zliczaj DW 35

Obowiązkowe jest tylko pole operacji. Pole operandów (argumentów) wystąpi wówczas, gdy będzie tego wymagać rozkaz, np. rozkaz STD nie ma tego pola. Pole etykiety nie musi być w każdej linii programu. Pole komentarza powinno wystąpić zawsze, i to tylko dla dobra programisty, a nie dla dobra asemblera. Niekiedy w programie może się zdarzyć, że zapis instrukcji asemblerowej w jednej linii będzie zbyt długi i przez to nieczytelny. W takim przypadku - bez żadnego uszczerbku dla programu -zapis programu możemy kontynuować przenosząc wiersz do następnej linii, nie zapominając o umieszczeniu na końcu poprzedniego wiersza znaku kontynuacji w postaci backslash (\).

Dla początkującego programisty języka asembler niezbędną informacją jest od czego właściwie zacząć nasz pierwszy program. W tej kwestji pewnie odpowiedzi są tysiące w zależności od rodzaju używanego kompilatora. Struktura naszego kodu źródłowego musi być odpowiednio różna dla tych kompilatorów. Przeglądając zasoby sieci Internet jak i propozycje książkowe różnych wydawnictw stwierdziłem, że najbardziej popularnym kompilarotorem jest Turbo Assembler firmy Borland (lub raczej Inprise). Dla kompilatora Turbo Assembler możemy zastosować nastepujący szablon programu:

Model Small
.Code
start:
...
exitcode
end start
cseg segment
assume cs:cseg
start:
...
cseg ends
end start

Pierwsza wersja zaczyna się dyrektywą .model... Określa ona tzw. model pamięci, który jest głównie informacją mówiącą kompilatorowi o wielkości pamięci przeznaczonej dla tego programu. Dostępne są nastepujące modele:
• tiny (malutki) - kod i dane programu muszą zawierać się w jednym bloku, nie większym niż rozmiar segmentu czyli 64kB.
• small (mały) - kod i dane programu zawarte są w oddzielnych segmentach. Każdy z nich ma rozmiar mniejszy niż 64kB.
• medium (średni) - segment kodu może być większy niż 64kB, lecz segment danych musi się mieścić w tej wielkości.
• compact - rozmiar segmentu kodu musi być mniejszy niż 64kB, natopiast segment danych może przekraczać ta wielkość.
• large (duży) - kod programu jaki i dane mogą przekroczyć rozmiar 64kB ale pojedyncza tablica nie może przekroczyć tej bariery.
• huge (olbrzymi) - daje największe możliwości. Zarówno rozmiar kodu, danych i tablic może przekroczyć 64kB.

Przy dyrektywie model niejawnie wykonywana jest dyrektywa 'assume cs:code'. Informuje to kompilator, że numer segmentu kodu będzie pamiętany w rejestrze CS. Numer ten wpisywany jest automatycznie do CS w chwili uruchomienia programu, jest to numer segmentu wyznaczony przez dyrektywę 'end'. W drugiej wersji dyrektywę model zastępuje deklaracja segmentu: assume cs:cseg. Zwalnia to nas od programowych zmian segmentów (przedrostków DS, ES...itd.) w przypadku działania na zmiennych, gdyż kompilator automatycznie wie, wzglądem którego segmentu ma być adresowana dana. Dodatkowo możemy umieścić informację o adresie pamięci, gdzie będzie znajdował się wskazany segment.
Dostępne są następujące typy rozmieszczenia:
• byte - segment rozpocznie się od kolejnego bajtu, czyli praktycznie w dowolnym miejscu.
• word - segment będzie się rozpoczynał adresem parzystym na granicy słowa.
• dword - segment będzie się rozpoczynał adresem parzystym na granicy podwójnego słowa, czyli pod adresem podzielnym przez cztery.
• para - segment będzie się rozpoczynał adresem podzielnym przez szesnaście.
• page - segmnet będzie się rozpoczynał adresem podzielnym przez 256.

Każdy program bez względu na działanie korzysta z jakiś danych. Każdy język programowania posiada mechanizm deklaracji zmiennych i w przypadku asemblera są to:
db (declare byte - bajt). Wartość tego typu może reprezentować: liczbę całkowitą bez znaku z zakresu 0...255; liczbę całkowitą ze znakiem z zakresu -128...127; znak ASCII (odpowiednik char z języka C).
dw (declare word - słowo, 2 bajty). Wartość tego typu może reprezentować: liczbę całkowitą bez znaku z zakresu 0...65535; liczbę całkowitą ze znakiem z zakresu -32768...32767 (odpowiednik short z języka C).
dd (declare doubleword - podwójne słowo, 4 bajty). Wartość tego typu może reprezentować: liczbę całkowitą bez znaku z zakresu 0...232-1; liczbę całkowitą ze znakiem z zakresu -231...231-1; 32-bitową liczbę zmiennoprzecinkową (odpowiednik float z języka C); adres logiczny.
dq (declare quadword - poczwórne słowo, 8 bajtów). Wartość tego typu może reprezentować: liczbę całkowitą bez znaku z zakresu 0...264-1; liczbę całkowitą ze znakiem z zakresu -263...263-1; 64-bitową liczbę zmiennoprzecinkową (odpowiednik double z języka C).
dt (declare tenbyte - 10 bajtów). Wartość tego typu może reprezentować: liczbę całkowitą bez znaku z zakresu 0...280-1; liczbę całkowitą ze znakiem z zakresu -279...279-1; 80-bitową liczbę zmiennoprzecinkową.



top