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
Segment: 1234h
Offset: 5678h
──────────────────
Fizyczny: 1234h × 10h + 5678h = 12340h + 5678h = 179B8hSegmenty 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:
mov ax, ds:[0100h] ; czytaj z DS:0100h
mov ax, es:[bx] ; czytaj z ES:BX4. Jak DOS uruchamia program?#
Krok po kroku:#
Załadowanie do pamięci
- DOS rezerwuje blok pamięci
- Ładuje plik .EXE lub .COM
Tworzenie PSP (Program Segment Prefix)
- 256-bajtowy obszar przed programem
- Zawiera informacje środowiskowe, linię komend (80h, 81h-FFh)
Ustawienie rejestrów segmentowych
- CS:IP wskazuje na punkt wejścia
- DS i ES wskazują na PSP
- SS:SP wskazuje na stos
Przekazanie sterowania
- Skok do programu (CS:IP)
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#
| Cecha | COM | EXE |
|---|---|---|
| Rozmiar | Max 64 KB - 256 B | Praktycznie nieograniczony |
| Struktura | Prosty kod binarny | Nagłówek + kod + dane |
| Segmenty | Wszystko w jednym | Oddzielne CS, DS, SS |
| Punkt wejścia | Zawsze 0100h | Określony w nagłówku |
| Relokacja | Nie | Tak (adresy poprawiane) |
| Łatwość | Prostszy | Bardziej 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:
- Wczytuje program do pamięci
- Odczytuje tabelę relokacji
- Dla każdego wpisu dodaje adres segmentu ładowania do wartości pod wskazanym adresem
- Ustawia CS:IP i SS:SP zgodnie z nagłówkiem
Jeśli kod zawiera
MOV AX, SEG danei 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.
| Model | Kod | Dane | Opis |
|---|---|---|---|
| tiny | 64 KB | razem z kodem | Dla .COM |
| small | 64 KB | 64 KB | Standardowy |
| medium | >64 KB | 64 KB | Duży kod |
| compact | 64 KB | >64 KB | Dużo danych |
| large | >64 KB | >64 KB | Wszystko duże |
| huge | >64 KB | >64 KB (tablice >64KB) | Największy |
Rozmiar wskaźników i tryb adresowania#
Model TINY/SMALL/COMPACT (near code):#
CALL proceduraGeneruje: 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):#
CALL proceduraGeneruje: 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#
| Dyrektywa | Rozmiar |
|---|---|
| DB | 1 bajt |
| DW | 2 bajty (1 słowo) |
| DD | 4 bajty (2 słowa) |
| DF | 6 bajtów |
| DQ | 8 bajtów |
| DT | 10 bajtów |
Przykłady:
Liczba dw ? ; 1 słowo, niezaincjalizowane
Liczby dw 1, 2, 3, 2000.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.
.data?
bufor db 100 dup(?) ; 100 bajtów nieokreślonych.code#
Początek sekcji kodu programu.
.code
start:
mov ax, @data ; inicjalizacja DS
mov ds, ax
; właściwy kod...
mov ax, 4C00h ; zakończenie
int 21h
end startend start - wskazuje punkt wejścia programu (etykietę start).
Szablon#
.model small
.stack 1024
.data
; {dane}
.code
main endp
; {kod}
main endp
end main7. 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.
| Rejestr | Pełna nazwa | Podział 8-bitowy | Typowe zastosowanie |
|---|---|---|---|
| AX | Accumulator | AH (high), AL (low) | akumulator – operacje arytmetyczne, I/O, wynik funkcji |
| BX | Base | BH, BL | rejestr bazowy – adresowanie pamięci, wskaźnik tablic |
| CX | Counter | CH, CL | licznik – pętle, operacje stringowe, przesunięcia |
| DX | Data | DH, DL | dane – 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.
mulużywa AX,loopsprawdza CX)
Rejestry wskaźnikowe i indeksowe (Pointer and Index Registers)#
| Rejestr | Pełna nazwa | Zastosowanie |
|---|---|---|
| SP | Stack Pointer | wskaźnik wierzchołka stosu – adresuje bieżący element na stosie |
| BP | Base Pointer | wskaźnik bazowy ramki stosu – dostęp do parametrów i zmiennych lokalnych |
| SI | Source Index | indeks źródłowy – operacje stringowe, adresowanie tablic |
| DI | Destination Index | indeks 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).
| Rejestr | Pełna nazwa | Zastosowanie | Domyślny offset |
|---|---|---|---|
| CS | Code Segment | segment kodu – określa, gdzie znajduje się kod programu | IP |
| DS | Data Segment | segment danych – dostęp do zmiennych globalnych | BX, SI, DI |
| SS | Stack Segment | segment stosu – określa położenie stosu | SP, BP |
| ES | Extra Segment | dodatkowy segment – operacje stringowe, dodatkowe dane | DI |
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)#
| Rejestr | Pełna nazwa | Zastosowanie |
|---|---|---|
| IP | Instruction Pointer | wskaź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ć
callz natychmiastowympop
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.
| Flaga | Nazwa | Bit | Znaczenie | Kiedy się ustawia (przykłady) |
|---|---|---|---|---|
| CF | Carry Flag | 0 | przeniesienie/pożyczka przy operacjach bez znaku (unsigned) | wynik dodawania przekracza 8/16 bitów; przy odejmowaniu pożyczka (np. sub ax,bx) |
| PF | Parity Flag | 2 | parzystość najmłodszego bajtu wyniku | jeśli najmłodszy bajt ma parzystą liczbę bitów = 1 |
| AF | Adjust Flag (Aux Carry) | 4 | przeniesienie/pożyczka między bitami 3 i 4 (BCD) | używane głównie przy arytmetyce BCD (daa, das) |
| ZF | Zero Flag | 6 | wynik operacji = 0 | każda instrukcja arytmetyczna/logiczna, której wynik daje zero |
| SF | Sign Flag | 7 | znak wyniku – kopia najbardziej znaczącego bitu (MSB) | wynik ma ustawiony bit najwyższego rzędu (wynik traktowany jako ujemny – signed) |
| TF | Trap Flag | 8 | tryb krokowy (single-step) | po ustawieniu powstaje przerwanie po każdej instrukcji (debugowanie) |
| IF | Interrupt Flag | 9 | włączenie przerwań maskowalnych | sti – włącza, cli – wyłącza przerwania maskowalne |
| DF | Direction Flag | 10 | kierunek operacji stringowych | 0 = inkrementacja (domyślnie), 1 = dekrementacja (std ustawia, cld czyści) |
| OF | Overflow Flag | 11 | przepeł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#
| Instrukcja | Opis | Przykład |
|---|---|---|
| MOV dest, src | Kopiuj src - dest | mov ax, 5 |
| XCHG a, b | Zamień miejscami | xchg ax, bx |
| LEA reg, mem | Załaduj adres | lea dx, tekst |
Uwaga: Nie można wykonać
mov mem, mem- tylko przez rejestr!
Ustawianie rejestrów:
mov ah, 02h ; do AH ładowana jest liczba 02h
mov dl, 07h ; do DL ładowana jest liczba 07hArytmetyka#
| Instrukcja | Opis | Flagi |
|---|---|---|
| ADD dest, src | dest = dest + src | ZF, CF, OF |
| SUB dest, src | dest = dest - src | ZF, CF, OF |
| INC dest | dest = dest + 1 | ZF, OF |
| DEC dest | dest = dest - 1 | ZF, OF |
| MUL src | AX = AL × src (8-bit) DX:AX = AX × src (16-bit) | CF, OF |
| DIV src | AL = AX ÷ src, AH = reszta (8-bit) AX = DX:AX ÷ src, DX = reszta (16-bit) | - |
Przykład:
mov al, 255
inc al ; AL = 0, ZF = 1, CF = 1Logika#
| Instrukcja | Opis |
|---|---|
| AND dest, src | Iloczyn logiczny |
| OR dest, src | Suma logiczna |
| XOR dest, src | Alternatywa rozłączna (exclusive or) |
| NOT dest | Negacja bitowa |
| TEST a, b | AND bez zapisywania (tylko flagi) |
Przesunięcia#
| Instrukcja | Opis |
|---|---|
| SHL dest, count | Shift left (× 2) |
| SHR dest, count | Shift right (÷ 2) |
| ROL dest, count | Rotate left |
| ROR dest, count | Rotate right |
Przykład:
mov cl, 3
shl ax, cl ; AX = AX × 8Porównania i skoki#
Etykieta:
start:Skok bezwarunkowy:
jmp etykietaInstrukcje porównania
| Instrukcja | Opis działania | Wpływ na flagi |
|---|---|---|
| CMP r/m, r/m/imm | odejmuje: lhs - rhs, ale nie zapisuje wyniku | ZF, SF, CF, OF, PF, AF ustawiane na podstawie wyniku odejmowania |
| TEST r/m, r/m/imm | AND bitowy, wynik nie jest zapisywany | ZF, SF, PF; CF i OF zawsze = 0; AF nieokreślone |
| CMP | TEST | |
|---|---|---|
| Działanie | wykonuje lhs - rhs (odejmowanie) | wykonuje lhs AND rhs |
| Wynik zapisany | nie | nie |
| Porównanie typów | signed i unsigned | zależności bitowe, maski, sprawdzenia pojedynczych bitów |
| Typowe zastosowania | porównania liczb, warunki >,<,= | sprawdzanie bitów, flag, testowanie pojedynczych właściwości |
Instrukcje skoku (warunkowe)
| Instrukcja | Warunek (flagi) | Znaczenie | |
|---|---|---|---|
| JE / JZ a | ZF = 1 | równe | op1 == op2 |
| JNE / JNZ a | ZF = 0 | różne | op1 != op2 |
| JC a | CF = 1 | carry = 1 | |
| JNC a | CF = 0 | carry = 0 | |
| JS a | SF = 1 | wynik ujemny (sign) | |
| JNS a | SF = 0 | wynik dodatni/zero | |
| JO a | OF = 1 | overflow | |
| JNO a | OF = 0 | brak overflow | |
| JP / JPE a | PF = 1 | parzystość | |
| JNP / JPO a | PF = 0 | nieparzystość |
BEZ ZNAKU (unsigned)
| Instrukcja | Warunek | Znaczenie | |
|---|---|---|---|
| JA a | (CF = 0) AND (ZF = 0) | większe (unsigned) | op1 > op2 |
| JAE / JNC a | CF = 0 | większe lub równe (unsigned) | op1 >= op2 |
| JB / JC a | CF = 1 | mniejsze (unsigned) | op1 < op2 |
| JBE a | (CF = 1) OR (ZF = 1) | mniejsze lub równe (unsigned) | op1 <= op2 |
ZE ZNAKIEM (signed)
| Instrukcja | Warunek | Znaczenie | |
|---|---|---|---|
| JG a | (ZF = 0) AND (SF = OF) | większe (signed) | op1 > op2 |
| JGE a | SF = OF | większe lub równe (signed) | op1 >= op2 |
| JL a | SF ≠ OF | mniejsze (signed) | op1 < op2 |
| JLE a | (ZF = 1) OR (SF ≠ OF) | mniejsze lub równe (signed) | op1 <= op2 |
Pętle#
| Instrukcja | Opis |
|---|---|
| LOOP label | CX–, jeśli CX ≠ 0 skocz |
mov cx, 10
petla:
; kod powtarzany 10 razy
loop petlaStos#
| Instrukcja | Opis |
|---|---|
| PUSH src | Włóż na stos |
| POP dest | Zdejmij ze stosu |
| PUSHF | Włóż flagi |
| POPF | Zdejmij flagi |
Procedury#
| Instrukcja | Opis |
|---|---|
| CALL proc | Wywołaj procedurę |
| RET | Powró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?#
- Program umieszcza parametry w rejestrach
- Wywołuje instrukcję
INT <numer> - Procesor:
- Zapisuje aktualny stan na stosie
- Skacze do procedury obsługi przerwania
- Po zakończeniu wraca do programu
Przykład: wyświetlenie znaku#
mov ah, 02h ; funkcja 02h - wypisz znak
mov dl, 'A' ; znak do wyświetlenia
int 21h ; wywołaj DOSTabela 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) | Opis | Parametry wejściowe | Wynik |
|---|---|---|---|
| 01h | Czytaj znak z echo | - | AL = znak |
| 02h | Wypisz znak | DL = znak | - |
| 08h | Czytaj znak bez echo | - | AL = znak |
| 09h | Wypisz string | DS:DX = adres (kończy $) | - |
| 0Ah | Buforowany input | DS:DX = bufor | - |
| 3Ch | Utwórz plik | DS:DX = nazwa, CX = atrybuty | AX = uchwyt / błąd |
| 3Dh | Otwórz plik | DS:DX = nazwa, AL = tryb | AX = uchwyt / błąd |
| 3Eh | Zamknij plik | BX = uchwyt | - |
| 40h | Zapisz do pliku | BX = uchwyt, DS:DX = dane, CX = długość | AX = zapisane bajty |
| 3Fh | Czytaj z pliku | BX = uchwyt, DS:DX = bufor, CX = długość | AX = przeczytane bajty |
| 42h | Przesuń wskaźnik | BX = uchwyt, CX:DX = pozycja, AL = tryb | DX:AX = nowa pozycja |
| 4Ch | Zakończ program | AL = kod powrotu | - |
Tryb otwarcia pliku (funkcja 3Dh, rejestr AL):
- 00h = tylko odczyt
- 01h = tylko zapis
- 02h = odczyt/zapis
mov ah, 02h
mov dl, 07h
int 21hwywołuje funkcję 02h przerwania 21h, która wysyła znak 07h (BEL / dzwonek).
Tabela funkcji INT 10h dla trybu tekstowego#
| AH | Funkcja | Parametry wejściowe | Parametry wyjściowe | Opis |
|---|---|---|---|---|
| 00h | Set Video Mode | AL = tryb wideo (03h = 80x25 tekst kolorowy) | - | Ustawia tryb pracy karty graficznej |
| 01h | Set Cursor Shape | CH = linia początkowa CL = linia końcowa | - | Zmienia wygląd kursora (rozmiar, widoczność) |
| 02h | Set Cursor Position | BH = strona DH = wiersz (0-24) DL = kolumna (0-79) | - | Ustawia pozycję kursora na ekranie |
| 03h | Get Cursor Position | BH = strona | CH = kształt początek CL = kształt koniec DH = wiersz DL = kolumna | Odczytuje pozycję i kształt kursora |
| 05h | Select Active Page | AL = numer strony (0-7) | - | Przełącza aktywną stronę ekranu |
| 06h | Scroll Window Up | AL = 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 |
| 07h | Scroll Window Down | AL = liczba linii BH = atrybut CH,CL = lewy górny róg DH,DL = prawy dolny róg | - | Przewija okno w dół |
| 08h | Read Character and Attribute | BH = strona | AH = atrybut AL = znak | Odczytuje znak i jego atrybut z pozycji kursora |
| 09h | Write Character and Attribute | AL = znak BH = strona BL = atrybut CX = liczba powtórzeń | - | Wyświetla znak z atrybutem (kursor się nie przesuwa) |
| 0Ah | Write Character Only | AL = znak BH = strona CX = liczba powtórzeń | - | Wyświetla znak bez zmiany atrybutu |
| 0Eh | Teletype Output | AL = znak BH = strona BL = kolor (tryb graficzny) | - | Wyświetla znak jak terminal (z obsługą \n, \r, \b) |
| 0Fh | Get Video Mode | - | AH = liczba kolumn AL = tryb wideo BH = aktywna strona | Pobiera informacje o aktualnym trybie |
| 13h | Write String | AL = 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ść | Kolor | Wartość | Kolor |
|---|---|---|---|
| 0 | Czarny | 8 | Ciemnoszary |
| 1 | Niebieski | 9 | Jasnoniebieski |
| 2 | Zielony | A | Jasnozielony |
| 3 | Cyjan | B | Jasny cyjan |
| 4 | Czerwony | C | Jasnoczerwony |
| 5 | Magenta | D | Jasna magenta |
| 6 | Brązowy | E | Żółty |
| 7 | Jasnoszary | F | Biały |
Przykłady użycia:#
Przykład 1: Czyszczenie ekranu#
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 10hPrzykład 2: Wyświetlanie kolorowego tekstu#
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 10hPrzykład 3: Wyświetlanie tekstu funkcją teletype#
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#
mov ah, 01h ; Set cursor shape
mov ch, 20h ; Bit 5 = 1 ukrywa kursor
mov cl, 0
int 10hPrzykład 5: Wyświetlanie całego ciągu#
.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 10h11. Wskazówki#
Zawsze inicjalizuj DS na początku programu:
mov ax, @data mov ds, axZawsze kończ programem prawidłowo:
mov ax, 4C00h int 21hNie można kopiować pamięć-pamięć bezpośrednio:
; ŹLE: mov [zmienna1], [zmienna2] ; DOBRZE: mov ax, [zmienna2] mov [zmienna1], axRozmiary muszą się zgadzać:
; ŹLE: mov al, word ptr [zmienna] ; AL to 8-bit, word to 16-bit ; DOBRZE: mov ax, word ptr [zmienna]String musi kończyć się znakiem $ dla funkcji 09h:
tekst db "String musi kończyć się znakiem $"
Materiały dodatkowe - sporo staroci#
Dokumentacja techniczna#
- Intel 8086 Family User’s Manual - oficjalna dokumentacja procesora 9800722-03_The_8086_Family_Users_Manual_Oct79.pdf
- MASM 6.1 Programmer’s Guide - dokumentacja asemblera Microsoft Microsoft_Macro_Assembler_6.0_Programmers_Guide_1991.pdf
- Art of Assembly Language (16-bit) - Randall Hyde: https://www.plantation-productions.com/Webster/www.artofasm.com/DOS/index.html
- PC Assembly Language - Paul A. Carter (darmowy PDF) pcasm-book.pdf
- x86 Opcode and Instruction Reference - http://ref.x86asm.net/
Tutoriale i kursy online#
- Tutorials Point - Assembly Programming: https://www.tutorialspoint.com/assembly_programming/
- x86 Assembly Guide (University of Virginia): https://www.cs.virginia.edu/~evans/cs216/guides/x86.html
- Assembly Language Tutorial (Derek Banas): seria video na YouTube (ARM) Assembly Language Tutorial - YouTube
Narzędzia i środowiska#
- DOSBox - emulator DOS: https://www.dosbox.com/
- MASM/TASM - asemblery dla DOS
- Turbo Debugger - debugger dla programów DOS
- NASM - alternatywny assembler: https://www.nasm.us/
- WinASM - IDE dla programowania w assemblerze
Referencje online#
- OSDev Wiki - niskopoziomowe programowanie: https://wiki.osdev.org/
- Felix Cloutier’s x86 Reference: https://www.felixcloutier.com/x86/
- Sandpile.org - szczegółowe informacje o architekturach x86
Tryb graficzny (Mode 13h)#
- Michael Abrash’s Graphics Programming Black Book - klasyka grafiki VGA
- VGA Hardware Programming: http://www.osdever.net/FreeVGA/home.htm
- Mode 13h Tutorial - liczne tutoriale na YouTube i blogach
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#
- gynvael.coldwind//vx + youtube: GynvaelColdwind - YouTube
- flat assembler Board: https://board.flatassembler.net/
- Vogons Programming Forum - retro programowanie
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#
- “Masters of Doom” - historia id Software (programowanie DOS)
- Demoscene archives - pouët.net :: your online demoscene resource, SCENE.ORG
- “Tricks of the Game Programming Gurus” - André LaMothe