Wstęp do Asemblera x86 16-bit

1. Czym jest asembler i architektura x86?

Asembler to język programowania niskiego poziomu, w którym każda instrukcja odpowiada niemal bezpośrednio jednej operacji procesora. Programujemy “blisko sprzętu”.

Architektura x86 to rodzina procesorów zapoczątkowana przez Intel 8086 (1978). Procesor 16-bitowy oznacza, że podstawowa jednostka danych to 16 bitów (2 bajty).

2. Tryby pracy procesora x86

Procesor x86 może działać w różnych trybach:

Real Mode (Tryb rzeczywisty)

  • Oryginalny tryb procesora 8086
  • Dostęp do maksymalnie 1 MB pamięci (20-bitowy adres)
  • Brak ochrony pamięci

Protected Mode (Tryb chroniony)

  • Wprowadzony w 80286
  • Pełna ochrona pamięci, wielozadaniowość
  • 32-bitowe adresy (dostęp do 4 GB RAM)

3. Segmentacja pamięci

Problem adresowania

Procesor 16-bitowy może operować na liczbach 0-65535 (FFFFh). Jak więc dostać się do 1 MB pamięci (adresy 0-1048575)?

Rozwiązanie: adresowanie segment:offset

Adres fizyczny = Segment × 16 + Offset

1
2
3
4
Segment:  1234h
Offset:   5678h
──────────────────
Fizyczny: 1234h × 10h + 5678h = 12340h + 5678h = 179B8h

Segmenty w procesorze

Procesor ma specjalne rejestry segmentowe:

  • CS (Code Segment) - kod programu
  • DS (Data Segment) - dane
  • SS (Stack Segment) - stos
  • ES (Extra Segment) - dodatkowy segment danych

Przykład dostępu do pamięci:

1
2
mov ax, ds:[0100h]  ; czytaj z DS:0100h
mov ax, es:[bx]     ; czytaj z ES:BX

4. Jak DOS uruchamia program?

Krok po kroku:

  1. Załadowanie do pamięci

    • DOS rezerwuje blok pamięci
    • Ładuje plik .EXE lub .COM
  2. Tworzenie PSP (Program Segment Prefix)

    • 256-bajtowy obszar przed programem
    • Zawiera informacje środowiskowe, linię komend (80h, 81h-FFh)
  3. Ustawienie rejestrów segmentowych

    • CS:IP wskazuje na punkt wejścia
    • DS i ES wskazują na PSP
    • SS:SP wskazuje na stos
  4. Przekazanie sterowania

    • Skok do programu (CS:IP)
  5. Po zakończeniu

    • Program wywołuje INT 21h, funkcja 4Ch
    • DOS zwalnia pamięć i przywraca kontrolę

5. Różnica między plikami COM i EXE

CechaCOMEXE
RozmiarMax 64 KB - 256 BPraktycznie nieograniczony
StrukturaProsty kod binarnyNagłówek + kod + dane
SegmentyWszystko w jednymOddzielne CS, DS, SS
Punkt wejściaZawsze 0100hOkreślony w nagłówku
RelokacjaNieTak (adresy poprawiane)
ŁatwośćProstszyBardziej elastyczny

EXE

  • Nagłówek EXE (MZ header) - 28 bajtów minimalnie:
    • Sygnatura “MZ” (4Dh 5Ah)
    • Rozmiar ostatniej strony
    • Liczba stron ( 512-bajtowych)
    • Liczba wpisów relokacyjnych
    • Rozmiar nagłówka w paragrafach
    • Minimalna/maksymalna pamięć dodatkowa
    • Początkowe wartości SS:SP i CS:IP
    • Offset tabeli relokacji
  • Tablica relokacji - lista adresów wymagających modyfikacji
  • Kod programu - segment CODE z instrukcjami
  • Dane programu - segment DATA z zainicjalizowanymi danymi
  • Segment stosu - STACK (jeśli zdefiniowany dyrektywą .stack)

Relokacja w EXE

Program EXE jest relokowalny, ponieważ:

  • Może być ładowany pod dowolny adres w pamięci
  • Zawiera tabelę relokacji z adresami, które trzeba poprawić
  • Przy ładowaniu, DOS:
    1. Wczytuje program do pamięci
    2. Odczytuje tabelę relokacji
    3. Dla każdego wpisu dodaje adres segmentu ładowania do wartości pod wskazanym adresem
    4. Ustawia CS:IP i SS:SP zgodnie z nagłówkiem

Jeśli kod zawiera MOV AX, SEG dane i program załadowano pod segment 1000h, DOS doda 1000h do wartości segmentu zapisanej w kodzie.

Brak relokacji w COM

Program COM jest nierelokowalny:

  • Jest zawsze ładowany pod stały adres 100h (w segmencie PSP)
  • Wszystkie adresy są obliczone na etapie kompilacji dla tego konkretnego offsetu
  • Nie ma nagłówka ani tabeli relokacji
  • Cały segment (CS=DS=ES=SS) wskazuje na ten sam obszar pamięci
  • Program jest po prostu “zrzutem pamięci” gotowym do wykonania

6. Dyrektywy asemblera MASM

Dyrektywy to instrukcje dla asemblera, nie dla procesora. Nie generują kodu maszynowego, tylko organizują program.

.model small

Określa model pamięci programu. Wpływa bezpośrednio na generowany kod maszynowy.

ModelKodDaneOpis
tiny64 KBrazem z kodemDla .COM
small64 KB64 KBStandardowy
medium>64 KB64 KBDuży kod
compact64 KB>64 KBDużo danych
large>64 KB>64 KBWszystko duże
huge>64 KB>64 KB (tablice >64KB)Największy

Rozmiar wskaźników i tryb adresowania

Model TINY/SMALL/COMPACT (near code):
1
CALL procedura

Generuje: E8 xx xx (3 bajty - relative near call)

  • Offset względny 16-bit
  • Zakłada, że procedura jest w tym samym segmencie kodu

Model MEDIUM/LARGE/HUGE (far code):

1
CALL procedura

Generuje: 9A xx xx yy yy (5 bajtów - absolute far call)

  • Pełny adres: offset (2 bajty) + segment (2 bajty)
  • Może wywołać procedurę w innym segmencie

.stack 512

Rezerwuje 512 bajtów na stos programu. Stos służy do:

  • Przechowywania adresów powrotu z funkcji
  • Zmiennych lokalnych
  • Tymczasowego przechowywania rejestrów

Można zmienić rozmiar, np. .stack 1024.

COM:
  • Dyrektywa jest IGNOROWANA
  • Program COM ma z góry ustalony stos na końcu dostępnej pamięci
  • Rejestr SP wskazuje na koniec segmentu (offset FFFEh lub FFFFh)
  • Stos “rośnie w dół” od końca dostępnych 64KB
  • Nie ma kontroli nad wielkością stosu w pliku COM
EXE:
  • Dyrektywa tworzy osobny segment stosu o wielkości XXX bajtów
  • Linker umieszcza ten segment w pliku wykonywalnym
  • Rejestry SS:SP są inicjalizowane przez loader systemu operacyjnego
  • SP wskazuje na koniec zaalokowanego obszaru stosu (offset XXX)
  • Rozmiar stosu można precyzyjnie kontrolować

.data

Początek sekcji zainicjalizowanych danych. Tu deklarujemy zmienne z wartościami początkowymi.

Deklaracja zmiennych

DyrektywaRozmiar
DB1 bajt
DW2 bajty (1 słowo)
DD4 bajty (2 słowa)
DF6 bajtów
DQ8 bajtów
DT10 bajtów

Przykłady:

1
2
Liczba  dw ?             ; 1 słowo, niezaincjalizowane
Liczby  dw 1, 2, 3, 2000
1
2
3
4
.data
    liczba dw 100
    tekst db "Hello$"
    tablica db 1, 2, 3, 4, 5

.data?

Sekcja niezainicjalizowanych danych (opcjonalna). Zmienne bez wartości początkowej.

1
2
.data?
    bufor db 100 dup(?)  ; 100 bajtów nieokreślonych

.code

Początek sekcji kodu programu.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.code
start:
    mov ax, @data    ; inicjalizacja DS
    mov ds, ax
    
    ; właściwy kod...
    
    mov ax, 4C00h    ; zakończenie
    int 21h
end start

end start - wskazuje punkt wejścia programu (etykietę start).

Szablon

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
.model small  
.stack 1024

.data
    ; {dane}

.code

main endp

    ; {kod}

main endp
end main

7. Rejestry procesora

Rejestry ogólnego przeznaczenia (General Purpose Registers)

Procesory x86 w trybie 16-bitowym dysponują czterema głównymi rejestrami ogólnego przeznaczenia, z których każdy może być używany jako jeden rejestr 16-bitowy lub dwa oddzielne rejestry 8-bitowe.

RejestrPełna nazwaPodział 8-bitowyTypowe zastosowanie
AXAccumulatorAH (high), AL (low)akumulator – operacje arytmetyczne, I/O, wynik funkcji
BXBaseBH, BLrejestr bazowy – adresowanie pamięci, wskaźnik tablic
CXCounterCH, CLlicznik – pętle, operacje stringowe, przesunięcia
DXDataDH, DLdane – I/O portów, mnożenie/dzielenie (starsze bity)

Uwagi:

  • Rejestry te można używać wymiennie w większości operacji arytmetycznych i logicznych
  • Podział na części wysoką (H - high) i niską (L - low) pozwala na efektywną pracę z danymi 8-bitowymi
  • Niektóre instrukcje wymagają konkretnego rejestru (np. mul używa AX, loop sprawdza CX)

Rejestry wskaźnikowe i indeksowe (Pointer and Index Registers)

RejestrPełna nazwaZastosowanie
SPStack Pointerwskaźnik wierzchołka stosu – adresuje bieżący element na stosie
BPBase Pointerwskaźnik bazowy ramki stosu – dostęp do parametrów i zmiennych lokalnych
SISource Indexindeks źródłowy – operacje stringowe, adresowanie tablic
DIDestination Indexindeks docelowy – operacje stringowe, adresowanie tablic

Uwagi:

  • SP automatycznie modyfikowany przez push, pop, call, ret
  • BP typowo używany do budowania ramek stosu w procedurach
  • SI i DI pracują razem w instrukcjach stringowych (movsb, cmpsb, etc.)
  • Rejestry te nie mają podziału na części 8-bitowe

Rejestry segmentowe (Segment Registers)

W architekturze x86 adres fizyczny jest tworzony z pary: rejestr segmentowy + offset. Każdy segment może mieć maksymalnie 64KB (0000h-FFFFh).

RejestrPełna nazwaZastosowanieDomyślny offset
CSCode Segmentsegment kodu – określa, gdzie znajduje się kod programuIP
DSData Segmentsegment danych – dostęp do zmiennych globalnychBX, SI, DI
SSStack Segmentsegment stosu – określa położenie stosuSP, BP
ESExtra Segmentdodatkowy segment – operacje stringowe, dodatkowe daneDI

Uwagi:

  • Adres fizyczny = Segment × 16 + Offset (np. CS:IP, DS:BX, SS:SP)
  • Rejestry segmentowe nie mogą być używane bezpośrednio w operacjach arytmetycznych
  • Zmiana CS możliwa tylko przez instrukcje skoku dalekiego (jmp far, call far, retf)
  • W małych modelach pamięci (.model small) często wszystkie segmenty wskazują na ten sam obszar

Rejestr wskaźnika instrukcji (Instruction Pointer)

RejestrPełna nazwaZastosowanie
IPInstruction Pointerwskaźnik następnej instrukcji do wykonania (w obrębie CS)

Uwagi:

  • Nie można bezpośrednio odczytać ani zapisać wartości IP
  • IP jest modyfikowany automatycznie przez procesor oraz instrukcje skoku i wywołań
  • Adres fizyczny następnej instrukcji: CS:IP
  • Do pośredniego dostępu można użyć call z natychmiastowym pop

Rejestr flag procesora (Flags Register)

Rejestr flag to specjalny 16-bitowy rejestr zawierający bity informacyjne o wyniku ostatniej operacji oraz kontrolujące tryb pracy procesora.

FlagaNazwaBitZnaczenieKiedy się ustawia (przykłady)
CFCarry Flag0przeniesienie/pożyczka przy operacjach bez znaku (unsigned)wynik dodawania przekracza 8/16 bitów; przy odejmowaniu pożyczka (np. sub ax,bx)
PFParity Flag2parzystość najmłodszego bajtu wynikujeśli najmłodszy bajt ma parzystą liczbę bitów = 1
AFAdjust Flag (Aux Carry)4przeniesienie/pożyczka między bitami 3 i 4 (BCD)używane głównie przy arytmetyce BCD (daa, das)
ZFZero Flag6wynik operacji = 0każda instrukcja arytmetyczna/logiczna, której wynik daje zero
SFSign Flag7znak wyniku – kopia najbardziej znaczącego bitu (MSB)wynik ma ustawiony bit najwyższego rzędu (wynik traktowany jako ujemny – signed)
TFTrap Flag8tryb krokowy (single-step)po ustawieniu powstaje przerwanie po każdej instrukcji (debugowanie)
IFInterrupt Flag9włączenie przerwań maskowalnychsti – włącza, cli – wyłącza przerwania maskowalne
DFDirection Flag10kierunek operacji stringowych0 = inkrementacja (domyślnie), 1 = dekrementacja (std ustawia, cld czyści)
OFOverflow Flag11przepełnienie dla wartości ze znakiem (signed)wynik arytmetyczny wykracza poza zakres signed (np. +32767 + 1 → -32768)

Uwagi:

  • Flagi CF, PF, AF, ZF, SF, OF – flagi stanu (modyfikowane przez operacje arytmetyczne/logiczne)
  • Flagi TF, IF, DF – flagi kontrolne (kontrolują tryb pracy procesora)
  • Dostęp do rejestru flag: pushf (odłóż na stos), popf (zdejmij ze stosu)
  • Instrukcje warunkowe (jz, jc, jg, etc.) sprawdzają kombinacje flag
  • Bity 1, 3, 5, 12-15 są zarezerwowane (zawsze = 0 w 8086/80286)

8. Podstawowe instrukcje asemblera

Przesyłanie danych

InstrukcjaOpisPrzykład
MOV dest, srcKopiuj src - destmov ax, 5
XCHG a, bZamień miejscamixchg ax, bx
LEA reg, memZaładuj adreslea dx, tekst

Uwaga: Nie można wykonać mov mem, mem - tylko przez rejestr!

Ustawianie rejestrów:

1
2
mov ah, 02h    ; do AH ładowana jest liczba 02h
mov dl, 07h    ; do DL ładowana jest liczba 07h

Arytmetyka

InstrukcjaOpisFlagi
ADD dest, srcdest = dest + srcZF, CF, OF
SUB dest, srcdest = dest - srcZF, CF, OF
INC destdest = dest + 1ZF, OF
DEC destdest = dest - 1ZF, OF
MUL srcAX = AL × src (8-bit)
DX:AX = AX × src (16-bit)
CF, OF
DIV srcAL = AX ÷ src, AH = reszta (8-bit)
AX = DX:AX ÷ src, DX = reszta (16-bit)
-

Przykład:

1
2
mov al, 255
inc al        ; AL = 0, ZF = 1, CF = 1

Logika

InstrukcjaOpis
AND dest, srcIloczyn logiczny
OR dest, srcSuma logiczna
XOR dest, srcAlternatywa rozłączna (exclusive or)
NOT destNegacja bitowa
TEST a, bAND bez zapisywania (tylko flagi)

Przesunięcia

InstrukcjaOpis
SHL dest, countShift left (× 2)
SHR dest, countShift right (÷ 2)
ROL dest, countRotate left
ROR dest, countRotate right

Przykład:

1
2
mov cl, 3
shl ax, cl    ; AX = AX × 8

Porównania i skoki

Etykieta:

1
start:

Skok bezwarunkowy:

1
jmp etykieta

Instrukcje porównania

InstrukcjaOpis działaniaWpływ na flagi
CMP r/m, r/m/immodejmuje: lhs - rhs, ale nie zapisuje wynikuZF, SF, CF, OF, PF, AF ustawiane na podstawie wyniku odejmowania
TEST r/m, r/m/immAND bitowy, wynik nie jest zapisywanyZF, SF, PF; CF i OF zawsze = 0; AF nieokreślone
CMPTEST
Działaniewykonuje lhs - rhs (odejmowanie)wykonuje lhs AND rhs
Wynik zapisanynienie
Porównanie typówsigned i unsignedzależności bitowe, maski, sprawdzenia pojedynczych bitów
Typowe zastosowaniaporównania liczb, warunki >,<,=sprawdzanie bitów, flag, testowanie pojedynczych właściwości

Instrukcje skoku (warunkowe)

InstrukcjaWarunek (flagi)Znaczenie
JE / JZ aZF = 1równeop1 == op2
JNE / JNZ aZF = 0różneop1 != op2
JC aCF = 1carry = 1
JNC aCF = 0carry = 0
JS aSF = 1wynik ujemny (sign)
JNS aSF = 0wynik dodatni/zero
JO aOF = 1overflow
JNO aOF = 0brak overflow
JP / JPE aPF = 1parzystość
JNP / JPO aPF = 0nieparzystość

BEZ ZNAKU (unsigned)

InstrukcjaWarunekZnaczenie
JA a(CF = 0) AND (ZF = 0)większe (unsigned)op1 > op2
JAE / JNC aCF = 0większe lub równe (unsigned)op1 >= op2
JB / JC aCF = 1mniejsze (unsigned)op1 < op2
JBE a(CF = 1) OR (ZF = 1)mniejsze lub równe (unsigned)op1 <= op2

ZE ZNAKIEM (signed)

InstrukcjaWarunekZnaczenie
JG a(ZF = 0) AND (SF = OF)większe (signed)op1 > op2
JGE aSF = OFwiększe lub równe (signed)op1 >= op2
JL aSF ≠ OFmniejsze (signed)op1 < op2
JLE a(ZF = 1) OR (SF ≠ OF)mniejsze lub równe (signed)op1 <= op2

Pętle

InstrukcjaOpis
LOOP labelCX–, jeśli CX ≠ 0 skocz
1
2
3
4
mov cx, 10
petla:
    ; kod powtarzany 10 razy
    loop petla

Stos

InstrukcjaOpis
PUSH srcWłóż na stos
POP destZdejmij ze stosu
PUSHFWłóż flagi
POPFZdejmij flagi

Procedury

InstrukcjaOpis
CALL procWywołaj procedurę
RETPowrót z procedury

9. Czym jest przerwanie (interrupt)?

Przerwanie to mechanizm komunikacji między programem a systemem operacyjnym lub BIOS-em.

Jak to działa?

  1. Program umieszcza parametry w rejestrach
  2. Wywołuje instrukcję INT <numer>
  3. Procesor:
    • Zapisuje aktualny stan na stosie
    • Skacze do procedury obsługi przerwania
    • Po zakończeniu wraca do programu

Przykład: wyświetlenie znaku

1
2
3
mov ah, 02h      ; funkcja 02h - wypisz znak
mov dl, 'A'      ; znak do wyświetlenia
int 21h          ; wywołaj DOS

Tabela przykładowych funkcji przerwania DOS (INT 21h)

INT 21h to główne przerwanie DOS-u do obsługi I/O, plików i systemu.

Funkcja (AH)OpisParametry wejścioweWynik
01hCzytaj znak z echo-AL = znak
02hWypisz znakDL = znak-
08hCzytaj znak bez echo-AL = znak
09hWypisz stringDS:DX = adres (kończy $)-
0AhBuforowany inputDS:DX = bufor-
3ChUtwórz plikDS:DX = nazwa, CX = atrybutyAX = uchwyt / błąd
3DhOtwórz plikDS:DX = nazwa, AL = trybAX = uchwyt / błąd
3EhZamknij plikBX = uchwyt-
40hZapisz do plikuBX = uchwyt, DS:DX = dane, CX = długośćAX = zapisane bajty
3FhCzytaj z plikuBX = uchwyt, DS:DX = bufor, CX = długośćAX = przeczytane bajty
42hPrzesuń wskaźnikBX = uchwyt, CX:DX = pozycja, AL = trybDX:AX = nowa pozycja
4ChZakończ programAL = kod powrotu-

Tryb otwarcia pliku (funkcja 3Dh, rejestr AL):

  • 00h = tylko odczyt
  • 01h = tylko zapis
  • 02h = odczyt/zapis
1
2
3
mov ah, 02h
mov dl, 07h
int 21h

wywołuje funkcję 02h przerwania 21h, która wysyła znak 07h (BEL / dzwonek).

Tabela funkcji INT 10h dla trybu tekstowego

AHFunkcjaParametry wejścioweParametry wyjścioweOpis
00hSet Video ModeAL = tryb wideo
(03h = 80x25 tekst kolorowy)
-Ustawia tryb pracy karty graficznej
01hSet Cursor ShapeCH = linia początkowa
CL = linia końcowa
-Zmienia wygląd kursora (rozmiar, widoczność)
02hSet Cursor PositionBH = strona
DH = wiersz (0-24)
DL = kolumna (0-79)
-Ustawia pozycję kursora na ekranie
03hGet Cursor PositionBH = stronaCH = kształt początek
CL = kształt koniec
DH = wiersz
DL = kolumna
Odczytuje pozycję i kształt kursora
05hSelect Active PageAL = numer strony (0-7)-Przełącza aktywną stronę ekranu
06hScroll Window UpAL = liczba linii (0=wyczyść)
BH = atrybut
CH,CL = lewy górny róg
DH,DL = prawy dolny róg
-Przewija okno w górę lub czyści ekran
07hScroll Window DownAL = liczba linii
BH = atrybut
CH,CL = lewy górny róg
DH,DL = prawy dolny róg
-Przewija okno w dół
08hRead Character and AttributeBH = stronaAH = atrybut
AL = znak
Odczytuje znak i jego atrybut z pozycji kursora
09hWrite Character and AttributeAL = znak
BH = strona
BL = atrybut
CX = liczba powtórzeń
-Wyświetla znak z atrybutem (kursor się nie przesuwa)
0AhWrite Character OnlyAL = znak
BH = strona
CX = liczba powtórzeń
-Wyświetla znak bez zmiany atrybutu
0EhTeletype OutputAL = znak
BH = strona
BL = kolor (tryb graficzny)
-Wyświetla znak jak terminal (z obsługą \n, \r, \b)
0FhGet Video Mode-AH = liczba kolumn
AL = tryb wideo
BH = aktywna strona
Pobiera informacje o aktualnym trybie
13hWrite StringAL = tryb zapisu
BH = strona
BL = atrybut
CX = długość
DH,DL = pozycja
ES:BP = adres tekstu
-Wyświetla cały ciąg znaków

Kody atrybutów kolorów (dla BH/BL)

Format bajtu atrybutu: KBBBTTTT

  • K - miganie (1 bit)
  • BBB - kolor tła (3 bity)
  • TTTT - kolor tekstu (4 bity)

Kolory (0-15):

WartośćKolorWartośćKolor
0Czarny8Ciemnoszary
1Niebieski9Jasnoniebieski
2ZielonyAJasnozielony
3CyjanBJasny cyjan
4CzerwonyCJasnoczerwony
5MagentaDJasna magenta
6BrązowyEŻółty
7JasnoszaryFBiały

Przykłady użycia:

Przykład 1: Czyszczenie ekranu

1
2
3
4
5
6
mov ah, 06h      ; Scroll up
mov al, 0        ; Cały ekran
mov bh, 07h      ; Atrybut: białe na czarnym
mov cx, 0        ; Lewy górny (0,0)
mov dx, 184Fh    ; Prawy dolny (24,79)
int 10h

Przykład 2: Wyświetlanie kolorowego tekstu

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
mov ah, 02h      ; Ustaw kursor
mov bh, 0
mov dh, 10       ; Wiersz
mov dl, 20       ; Kolumna
int 10h

mov ah, 09h      ; Wyświetl znak z atrybutem
mov al, 'A'      ; Znak
mov bh, 0        ; Strona
mov bl, 1Eh      ; Żółty na niebieskim (tło=1, tekst=E)
mov cx, 5        ; Powtórz 5 razy
int 10h

Przykład 3: Wyświetlanie tekstu funkcją teletype

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
mov ah, 0Eh      ; Teletype
mov al, 'H'      ; Znak
mov bh, 0        ; Strona
int 10h          ; Wyświetl 'H'

mov al, 'i'
int 10h          ; Wyświetl 'i'

mov al, '!'
int 10h          ; Wyświetl '!'

Przykład 4: Ukrywanie kursora

1
2
3
4
mov ah, 01h      ; Set cursor shape
mov ch, 20h      ; Bit 5 = 1 ukrywa kursor
mov cl, 0
int 10h

Przykład 5: Wyświetlanie całego ciągu

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
.DATA
    tekst DB 'Hello World!'
    dlugosc EQU $-tekst

.CODE
    mov ah, 13h      ; Write string
    mov al, 1        ; Tryb 1: przesuwaj kursor, użyj BL
    mov bh, 0        ; Strona
    mov bl, 0Eh      ; Żółty na czarnym
    mov cx, dlugosc  ; Długość
    mov dh, 12       ; Wiersz
    mov dl, 35       ; Kolumna
    push ds
    pop es
    lea bp, tekst    ; ES:BP wskazuje na tekst
    int 10h

11. Wskazówki

  1. Zawsze inicjalizuj DS na początku programu:

    1
    2
    
    mov ax, @data
    mov ds, ax
    
  2. Zawsze kończ programem prawidłowo:

    1
    2
    
    mov ax, 4C00h
    int 21h
    
  3. Nie można kopiować pamięć-pamięć bezpośrednio:

    1
    2
    3
    4
    5
    6
    
    ; ŹLE:
    mov [zmienna1], [zmienna2]
    
    ; DOBRZE:
    mov ax, [zmienna2]
    mov [zmienna1], ax
    
  4. Rozmiary muszą się zgadzać:

    1
    2
    3
    4
    5
    
    ; ŹLE:
    mov al, word ptr [zmienna]  ; AL to 8-bit, word to 16-bit
    
    ; DOBRZE:
    mov ax, word ptr [zmienna]
    
  5. String musi kończyć się znakiem $ dla funkcji 09h:

    1
    
    tekst db "String musi kończyć się znakiem $"
    

Materiały dodatkowe - sporo staroci

Dokumentacja techniczna

Tutoriale i kursy online

Narzędzia i środowiska

Referencje online

Tryb graficzny (Mode 13h)

Przerwania DOS i BIOS

  • DOS API Reference - lista funkcji int 21h
  • BIOS Services Reference - funkcje int 10h, 16h, 13h
  • IBM PC BIOS Source Code - historyczny kod źródłowy

Społeczności i fora

Emulatowy i debugowanie

  • DOSBox-X - rozszerzona wersja DOSBox z lepszym debuggerem
  • QEMU - emulator z możliwością debugowania
  • Bochs - emulator x86 z wbudowanym debuggerem

Historie i ciekawostki