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
| |
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:
| |
4. 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):
| |
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):
| |
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
| 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:
| |
| |
.data?
Sekcja niezainicjalizowanych danych (opcjonalna). Zmienne bez wartości początkowej.
| |
.code
Początek sekcji kodu programu.
| |
end start - wskazuje punkt wejścia programu (etykietę start).
Szablon
| |
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.
| 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:
| |
Arytmetyka
| 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:
| |
Logika
| 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:
| |
Porównania i skoki
Etykieta:
| |
Skok bezwarunkowy:
| |
Instrukcje 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 |
| |
Stos
| 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
| |
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) | 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
| |
wywoł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
| |
Przykład 2: Wyświetlanie kolorowego tekstu
| |
Przykład 3: Wyświetlanie tekstu funkcją teletype
| |
Przykład 4: Ukrywanie kursora
| |
Przykład 5: Wyświetlanie całego ciągu
| |
11. Wskazówki
Zawsze inicjalizuj DS na początku programu:
1 2mov ax, @data mov ds, axZawsze kończ programem prawidłowo:
1 2mov ax, 4C00h int 21hNie można kopiować pamięć-pamięć bezpośrednio:
1 2 3 4 5 6; ŹLE: mov [zmienna1], [zmienna2] ; DOBRZE: mov ax, [zmienna2] mov [zmienna1], axRozmiary 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]String musi kończyć się znakiem $ dla funkcji 09h:
1tekst 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