Asembler 8086 — Ściągawka (tryb rzeczywisty, BIOS/DOS)

Klasyczny 16-bitowy asembler 8086/8088 w trybie rzeczywistym (real mode): segmentowy model pamięci, rejestry 16-bitowe oraz przerwania BIOS (int 10h) i DOS (int 21h). Składnia zgodna z MASM/TASM/emu8086 (Intel).

1. Rejestry 8086 (16-bit)

Rejestry ogólnego przeznaczenia

16-bitWyższy/niższy bajtZastosowanie
AXAH / ALAkumulator — wyniki, argumenty przerwań
BXBH / BLBazowy — jedyny (poza SI/DI/BP) do adresowania
CXCH / CLLicznik — pętle (LOOP), przesunięcia bitowe
DXDH / DLDane — dzielenie/mnożenie, porty We/Wy

Rejestry indeksowe i wskaźnikowe

  • SI — Source Index (źródło w operacjach łańcuchowych)
  • DI — Destination Index (cel w operacjach łańcuchowych)
  • BP — Base Pointer (adresowanie ramki stosu)
  • SP — Stack Pointer (szczyt stosu)
  • IP — Instruction Pointer (adres następnego rozkazu, niedostępny wprost)

Rejestry segmentowe

  • CS — segment kodu
  • DS — segment danych (domyślny dla [BX], [SI], [DI])
  • SS — segment stosu (domyślny dla [BP], SP)
  • ES — segment dodatkowy (m.in. cel operacji łańcuchowych, bufor wideo)

8086 ma tylko rejestry 16-bitowe — nie ma EAX, RAX itp. To jeszcze wersja "przed" 32-bitowym x86.

2. Segmentowy model pamięci

Adres fizyczny (20-bit, max 1 MB) liczony jest z pary segment:offset:

adres_fizyczny = segment * 16 + offset

Np. MOV ES, BX (gdy BX=0) ustawia segment ES na 0, a późniejsze MOV BP, OFFSET hello daje offset etykiety w bieżącym segmencie danych — razem wskazują konkretny bajt w pamięci.

  • Jeden fizyczny adres można zapisać wieloma parami segment:offset (segmenty się nakładają)
  • Domyślne skojarzenia: kod → CS, dane/BX/SI/DI → DS, stos/BP/SP → SS, łańcuchy (cel) → ES
  • Prefiks segmentu można wymusić: MOV AX, ES:[BX]

3. Dyrektywy i deklaracje danych

DyrektywaZnaczenie
DBDeklaracja bajtu / ciągu bajtów (Define Byte)
DWDeklaracja słowa, 2 bajty (Define Word)
DUPPowtórzenie wartości, np. tab DB 10 DUP(0)
OFFSETZwraca przesunięcie (offset) etykiety w segmencie
ORGUstawia adres początkowy kodu/danych
EQUDefiniuje stałą symboliczną
ENDKoniec pliku źródłowego programu
hello DB "Hello Worldd"   ; ciąg znaków (bez terminatora 0)
tab   DB 10 DUP(0)        ; 10 bajtów wyzerowanych
dlugosc EQU 11             ; stała = 11

4. Tryby adresowania

  • Natychmiastowe: MOV AX, 5
  • Rejestrowe: MOV AX, BX
  • Bezpośrednie: MOV AX, [zmienna] (adres w DS)
  • Pośrednie rejestrowe: MOV AX, [BX], [SI], [DI], [BP]
  • Bazowo-indeksowe: MOV AX, [BX+SI]
  • Z przemieszczeniem: MOV AX, [BX+4], [SI+2]

8086 pozwala łączyć w nawiasie tylko określone pary: BX lub BP (baza) z SI lub DI (indeks) — np. [BX+DI] jest legalne, ale [BX+CX] już nie.

5. Przesyłanie danych

InstrukcjaDziałanie
MOV dst, srcKopiuje wartość (nie może być mem→mem ani segment→segment wprost)
LEA dst, srcŁaduje offset efektywnego adresu do rejestru
LDS dst, srcŁaduje offset do dst i segment do DS jednocześnie
LES dst, srcJak wyżej, ale segment trafia do ES
PUSH / POPOdłożenie/zdjęcie słowa (2 bajty) ze stosu
XCHG a, bZamiana wartości miejscami

Nie można wprost zrobić MOV ES, 0 — rejestr segmentowy ładuje się tylko z innego rejestru lub pamięci, stąd trik MOV BX, 0 / MOV ES, BX w przykładzie z Hello World.

6. Arytmetyka i logika bitowa

InstrukcjaDziałanie
ADD / SUBDodawanie / odejmowanie
INC / DECZwiększenie / zmniejszenie o 1
MUL / IMULMnożenie bez znaku / ze znakiem (AX lub DX:AX)
DIV / IDIVDzielenie bez znaku / ze znakiem (DX:AX / src)
NEG / CMPNegacja / porównanie (jak SUB, tylko flagi)
AND / OR / XOR / NOTOperacje bitowe
SHL / SHRPrzesunięcie bitowe w lewo/prawo
ROL / RORRotacja bitów

7. Skoki, porównania, pętle

SkokWarunek
JMPBezwarunkowy
JE/JZ, JNE/JNZRówne/zero, różne
JG, JL, JGE, JLEZe znakiem: większe, mniejsze, ...
JA, JB, JAE, JBEBez znaku: większe, mniejsze, ...
MOV CX, 5
petla:
    ; ... ciało pętli ...
    LOOP petla     ; CX--, skok jeśli CX != 0

8. Instrukcje łańcuchowe (string)

Operują na DS:SI (źródło) i ES:DI (cel), z użyciem prefiksu REP. Kierunek (rosnąco/malejąco) ustawia flaga DF: CLD = w przód, STD = w tył.

InstrukcjaDziałanie
MOVSB / MOVSWKopiuje bajt/słowo z [SI] do [DI], SI/DI += 1 lub 2
LODSBŁaduje bajt z [SI] do AL, SI++
STOSBZapisuje AL pod [DI], DI++
CMPSBPorównuje bajty [SI] i [DI]
SCASBPorównuje AL z bajtem pod [DI]
REP / REPE / REPNEPowtarza operację CX razy / dopóki równe / dopóki różne

9. Procedury

moja_proc PROC
    ; ... ciało procedury ...
    RET
moja_proc ENDP

    CALL moja_proc

CALL odkłada adres powrotu na stos, RET go zdejmuje. W programach wieloplikowych/segmentowych rozróżnia się wywołania NEAR (w segmencie) i FAR (między segmentami, odkładają też CS).

10. Przerwania BIOS — INT 10h (usługi wideo)

AHFunkcja
0x00Ustaw tryb wideo (AL = numer trybu)
0x02Ustaw pozycję kursora (DH=wiersz, DL=kolumna)
0x0ETeletype output — wypisz znak z AL i przesuń kursor
0x13Wypisz ciąg znaków: ES:BP=adres, CX=długość, DL=kolumna startowa, DH=wiersz

Właśnie funkcja AH=0x13 jest użyta w przykładzie Hello World — wymaga ustawienia ES:BP na segment:offset napisu oraz CX na jego długość.

11. Przerwania DOS — INT 21h

AHFunkcja
0x01Odczyt znaku z klawiatury (z echem) do AL
0x02Wypisz jeden znak: DL = znak
0x09Wypisz ciąg zakończony znakiem $: DX = offset ciągu
0x4CZakończ program (AL = kod wyjścia)
napis DB "Hello, DOS!$"
...
MOV AH, 0x09
MOV DX, OFFSET napis
INT 0x21

MOV AH, 0x4C
INT 0x21

12. Kompilacja i uruchamianie

  • emu8086 — środowisko edukacyjne z wbudowanym emulatorem, kompilacją i debugerem
  • MASM/TASM — klasyczne asemblery DOS (MASM plik.asm, potem LINK)
  • DOSBox — emulator do uruchamiania programów .COM/.EXE ze starego DOS na nowoczesnym systemie
  • DEBUG.COM — wbudowany w DOS mini-debuger (komendy: a assemble, u unassemble, t trace, r registers)

Przykładowy program — "Hello World" przez przerwanie BIOS

; Program to show use of interrupts
; Also, Hello World program !

hello: DB "Hello Worldd"   ; store string

; actual entry point of the program, must be present
start:
MOV AH, 0x13            ; move BIOS interrupt number in AH
MOV CX, 11              ; move length of string in cx
MOV BX, 0               ; mov 0 to bx, so we can move it to es
MOV ES, BX              ; move segment start of string to es, 0
MOV BP, OFFSET hello    ; move start offset of string in bp
MOV DL, 0               ; start writing from col 0
INT 0x10                ; BIOS interrupt

Krok po kroku: AH=0x13 wybiera funkcję "wypisz ciąg" z usług wideo BIOS. CX ustawia liczbę znaków do wypisania. ES:BP wskazuje segment:offset napisu w pamięci (tu segment=0, offset = etykieta hello). DL to kolumna startowa. Sam INT 0x10 wykonuje właściwe wypisanie na ekran.

SŁOWNICZEK POJĘĆ