1. STRUKTURA PROGRAMU

.model tiny ;model pamięci "tiny", oznacza, że kod programu musi zmieścić się w 64KB
.code       ;początek sekcji kodu
org 100h    ;program będzie typu *.com, kod zacznie się od offsetu 100h

start:      ;początek etykiety start

(...)

end start   ;koniec etykiety start



2. Systemy liczbowe

Do programowania w Assemblerze przydatna będzie na pewno wiedza o dwóch dodatkowych systemach liczbowych (prócz dziesiętnego) takich jak: dwójkowy (binarny), szesnastkowy (heksadecymalny).
Opiszę krótko te dwa systemy:
binarny – podstawą systemu jest są dwie cyfry: 0 i 1. W tym systemie działa komputer, w tym systemie jest zapisywany kod programu. Liczby w tym systemie przyjęło się zapisywać z literą b na końcu (np. 10001011b).
heksadecymalny – podstawą systemu są cyfry od 0 do 9 i litery od A do F (w sumie szesnaście znaków). Dla człowieka o wiele bardziej wygodny od systemu binarnego. Liczby w tym systemie przyjęło zapisywać się z literą h na końcu (np. 23E0B3h).


To wszystko na temat systemów, jak ktoś chce może doczytać coś więcej o nich, a także nauczyć się je ręcznie przeliczać. Jednak programując szybciej i wygodniej jest przeliczać te systemy za pomocą kalkulatora. Dlatego jedziemy dalej.

 

3. Jednostki informacji pamięci komputerowej

Bit – najmniejsza część danych. Przyjmuje wartość 0 lub 1.

Bajt – jest to 8 bitów. Jego maksymalna wartość to 255d.

Word (Słowo) – 2 bajty, czyli 16 bitów. Maksymalna wartość to 0FFFFh (lub 65535d).

Double-Word (Podwójne słowo) – Dwa słowa, czyli 4bajty (32 bity). Maksymalna wartość to 0FFFFFFFF (lub 4294967295d).

Quad-Word (Poczwórne słowo) – Cztery słowa, czyli 8 bajtów (64 bity).

Kilobajt – 1024 bajty.

Megabajt – 1024 kilobajty, 1048576 bajtów.


3.1 ZMIENNE

zmienna1 db 0 ;zmienna o rozmiarze 1 bajta

zmienna2 dw 0 ;zmienna o rozmiarze pojedyńczego słowa (2 bajtów)

zmienna3 dd 0 ;zmienna o rozmiarze podwójnego słowa (4 bajtów)

zmienna4 pw 0 ;zmienna o rozmiarze potrójnego słowa (6 bajtów)

zmienna5 dq 0 ;zmienna o rozmiarze poczwórnego słowa (8 bajtów)

zmienna6 dt 0 ;zmienna o rozmiarze dziesięciu bajtów (DT - Define Ten (bytes))

zmienna7 db 256 dup(0) ;dyrektywa dup (duplicate) powoduje zarezerwowanie pamięci o podanym rozmiarze (w tym przypadku 256 bajtów) i wypełnienie go podaną wartością (w tym przypadku zerami)
.


4. REJESTRY PROCESORA

Teraz będzie dużo teorii, którą warto przeczytać, ale nie ma sensu kuć na pamięć, z czasem się zapamięta :)

Rejestry są to komórki pamięci wewnątrz procesora służące mu do wykonywania różnych operacji. Warto wspomnieć, że operacje na rejestrach są o wiele szybsze niż na zmiennych w pamięci. Rejestry ogólnego przeznaczenia są cztery (EAX, EBX, ECX i EDX). Mają one po 32 bity (4 bajty). Każdy z nich dzieli się na dwie części po 16 bitów (części te nazywają się HIGH-WORD i LOW-WORD). Weźmy na przykładzie rejestru EAX: Niższa część (LOW-WORD) to rejestr AX, który dzieli się znów na dwa rejestry 8 bitowe: AH i AL. Warto wspomnieć też, że te rejestry możemy używać do czego chcemy, ale każdy z nich ma swoje specjalne przeznaczenie.


Lecz to nie wszystkie rejestry. Są jeszcze dwa rejestry indeksowe (EDI i ESI), które dzielą się na DI i SI. Używa się ich do operacji na łańcuchach (np. na tekście). ESI przechowuje źródło (ang. Source), a EDI miejsce docelowe (ang. Destination). EBP i ESP to natomiast rejestry wskaźnikowe pierwszy z nich służy do adresowania, drugi przechowuje wskaźnik wierzchołka stosu.
Podobnie jak wyżej załączam ilustracje:

Pozostałe rejestry to:
- rejestry segmentowe (16 bitowe): CS (Code Segment), DS (Data Segment), ES (Extra Segment), SS (Stack Segment), FS, GS.
- rejestr flag: EFLAGS
- rejestry koprocesora: ST0…ST7, do operacji na liczbach zmiennoprzecinkowych.
- EIP - rejestr zawierający adres aktualnie wykonywanej instrukcji.

To już wszystkie rejestry, które by nas interesowały.

 

5. PRZYKŁADOWY PROGRAM

.model tiny
.code
org 100h

start:

    mov ah,9
    mov dx,offset info
    int 21h

    mov ah,0
    int 16h

    mov ax,4C00h
    int 21h

info db "PWSZ KROSNO $"

end start

 

5.1 OPIS INSTRUKCJI PROGRAMU

Pierwsza instrukcja naszego programu to mov. Jest to instrukcja kopiowania. Kod który widzimy nadaje rejestrowi ah wartość 9.
Inne przykłady użycia instrukcji mov:
mov ax, 0        ;rejestr ax przyjmuje wartość zero
mov zmienna, 123 ;zmienna o nazwie "zmienna" przyjmuje wartość 123
mov ax, cx       ;rejestr ax przyjmuje wartość rejestru cx
mov zmienna, ax  ;zmienna przyjmuje wartość rejestru
mov ax, offset zmienna ;w rejestrze ax będzie adres do tego co jest w zmiennej
                       ;załóżmy, że zmienna ma wartość 125. Zatem pisząc:
                       ;
mov ax, zmienna rejestr ax będzie miał wartość 125
                       ;jeżeli natomiast napiszemy:
                       ;
mov ax, offset zmienna to rejestr ax będzie miał adres
                       ;do tej wartości w pamięci.
                       ;offset używamy np. gdy chcemy do rejestru dać adres jakiegoś
                       ;łańcucha znaków, normalnie tekst by się nie zmieścił w rejestrze
                       ;więc dajemy adres do tego tekstu.


mov zmienna1, zmienna2 ;ten zapis jest BŁĘDNY, gdyż nie można skopiować wartości
                       ;ze zmiennej do innej zmiennej.

;zatem trzeba posłużyć się rejestrem pomocniczym (skopiować
;wartość do tego rejestru, a potem do zmiennej) lub
;odłożyć wartość na stos, a potem dać do innej zmiennej
;(o działaniach na stosie będzie później).

;skopiowanie wartości ze zmienna1 do zmienna2 przy pomocy rejestru pomocniczego
mov ax, zmienna1       ;ax przyjmuje wartość zmienna1
mov zmienna2, ax       ;zmienna 2 przyjmuje wartość ax

;skopiowanie wartości ze zmienna1 do zmienna2 przy użyciu stosu
push zmienna1          ;odłóż zmienna1 na stos (push)
pop zmienna2           ;zdejmij wartość ze stosu i daj do zmienna2 (pop)

 

Wracając do naszego programu. Następna linijka to mov dx,offset info.
Kopiuje ona adres pod którym znajduje się tekst "PWSZ KROSNO $" do rejestru dx.

Po czym następuje wywołanie przerwania o numerze 21h.

Potem jest przerwanie int 16h/ah=0, które czeka na naciśnięcie klawisza (zatrzymuje ono program, abyśmy mogli przeczytać wypisany tekst).

A po nim przerwanie kończące program (tj. int 21h/ax=4C00h).

Pod tym wszystkim widzimy zadeklarowaną zmienną o nazwie info, która zawiera ciąg znaków "PWSZ KROSNO $".
Zmienna jest wielkości 13 bajtów (wszystkie znaki razem ze spacjami i znakiem kończącym $).
Dyrektywa db użyta właśnie tam definiuje odpowiednią ilość bajtów (db - define byte).

 

5.2 KORZYSTANIE Z DOKUMENTACJI

Jeżeli chcemy programować to musimy nauczyć się korzystać z dokumentacji. Przecież cały czas nie będzie przy nas osoba, która przetłumaczy nam na język polski dokumentacje i opisze dokładnie co funkcja robi. Zatem teraz pokażę, jak łatwo dowiedzieć się co dane przerwanie wykonuje, bo nie znającej przerwań osobie numer 21h dużo nie mówi.

Zatem przeanalizujmy powyższy kod korzystając z dokumentacji z Internetu.
Pod tym adresem jest tablica przerwań wraz z opisem: http://www.ctyme.com/intr/int.htm
Wchodzimy na tą stronę i klikamy na link 21h (gdyż taki jest numer pierwszego przerwania z naszego programu: int 21h).

Widzimy bardzo długą listę przerwań, jak teraz znaleść to co jest w naszym programie?

Odnajdziemy je po parametrach, widzimy, że do rejestru ah kopiowana jest wartość 9, zatem szukamy takiej linijki na stronie:

Int 21/AH=09h - DOS 1+ - WRITE STRING TO STANDARD OUTPUT

Wszystko się zgadza, przerwanie numer 21h z parametrem 09h w rejestrze ah.

Klikamy w link i naszym oczom ukazuje się opis przerwania:

DOS 1+ - WRITE STRING TO STANDARD OUTPUT
AH = 09h
DS:DX -> '$'-terminated string


Return:
AL = 24h (the '$' terminating the string, despite official docs which
state that nothing is returned) (at least DOS 2.1-7.0 and
NWDOS)

Notes: ^C/^Break are checked, and INT 23 is called if either pressed. Standard output is always the screen under DOS 1.x, but may be redirected under DOS 2+. Under the FlashTek X-32 DOS extender, the pointer is in DS:EDX

Najpierw tłumaczymy nagłówek: WRITE STRING TO STANDARD OUTPUT - WYPISZ TEKST DO STANDARDOWEGO WYJŚCIA
Czyli już wiemy, że to przerwanie wypisuje tekst do standardowego wyjścia (u nas jest to konsola).
Następnie widzimy parametry jakie musimy podać:
Do rejestru ah musimy dać wartość 9, a do dx adres naszego tekstu zakończonego znakiem $.

Niżej po Return: widzimy opisane co przerwanie zwraca. Zwraca nam wartość 24h w rejestrze al. Tutaj akurat zwracana wartość nas nie interesuje, ale np. przerwanie pobierające aktualną datę, zwróci nam tą datę do jakiegoś rejestru i wtedy będziemy musieli na to zwrócić uwagę.

 

7. KOMPILACJA KODU ŹRÓDŁOWEGO DO PLIKU WYKONYWALNEGO (*.com)

kompilacja.html (wymagany Flash Player).

D.F.