Verder met TASM
Arnout van Kempen schrijft in deze rubriek over pret maken met computers. Hij gaat aan de slag met Pascal.
Tot nu toe keek ik naar registers en basisinstructies. Maar programmeren op een PC is méér dan de CPU; je praat ook met de machine zelf. Dat pad loopt historisch via BIOS en pas daarna via DOS.
BIOS vóór DOS — waarom dit zo briljant is (CP/M-erfenis)
In de CP/M-wereld werd het besturingssysteem bewust in lagen gesplitst:
- CCP (shell), BDOS (OS-diensten) en BIOS (hardwarelaag).
- Die BIOS-laag bevat alle machine-specifieke code. Port je naar een andere computer, dan herschrijf je alleen het BIOS; de rest blijft werken.
IBM neemt dit idee over: op de PC zet IBM de BIOS in ROM
- Dat levert een stabiele, uniforme interface dicht op de hardware (scherm, keyboard, disk).
- Software (DOS, applicaties) kan op elke IBM-compatibele machine draaien, zolang het BIOS dezelfde "contracten" nakomt.
En daar begint de clone war: wie een functioneel equivalent van IBM’s BIOS levert (Phoenix doet dat schoon-kamer), kan MS-DOS en DOS-software draaien op niet-IBM-hardware. BIOS ≠ DOS: het is firmware van de fabrikant; DOS is vervangbare software erbóven.
Waar DOS in het plaatje past
DOS wordt vanaf disk geladen:
- IO.SYS (basisdrivers/bootstrap)
- MSDOS.SYS (de kernel: OS-diensten)
- COMMAND.COM (de shell; vervangbaar door bijvoorbeeld 4DOS)
Programma's praten met DOS via INT 21h (de DOS-API). DOS zelf schakelt waar nodig door naar BIOS-INT's om hardware te bedienen. Kort: BIOS = ijzerlaag; DOS = OS-diensten en files; shell = vervangbaar programma.
Interrupts: wat en hoe (zonder meteen te "doen")
Een software-interrupt (INT n) is een sprong naar een vector in de Interrupt Vector Table (IVT) op 0000:0000. Mechaniek:
- CPU pusht FLAGS, CS, IP; zet interrupts uit (IF=0); springt naar handler van n.
- IRET zet IP, CS, FLAGS terug: je komt exact terug waar je was.
Hardware-interrupts doen hetzelfde, maar worden door devices getriggerd (via de PIC). Voor dit deel volstaat: we roepen DOS met INT 21h, BIOS met bijv. INT 10h/16h/13h.
INT 21h (DOS-API) in een notendop
Je zet het functienummer in AH, parameters in andere registers. Drie nuttige starters:
- AH=09h — print $-terminated string, DS:DX wijst naar de string
- AH=01h — lees één toets, ASCII in AL
- AH=4Ch — beëindig programma, exitcode in AL
BIOS-INT’s (voor het idee)
- INT 10h video (tekstkleur, cursor, modus)
- INT 16h keyboard (toets ophalen)
- INT 13h disk (sector I/O)
Zo zie je de scheidslijn: BIOS = device-nabij; DOS = files, processen, algemene diensten.
SI/DI en veilig kopiëren: een compleet voorbeeld
We laten zien hoe je een string kopieert met REP MOVSB en vervolgens print via DOS. De kern: lengte correct bepalen en voldoende doelruimte reserveren.
ORG 100h
START:
; 1) Kopieer SRC → DEST (exact LEN bytes)
mov si,OFFSET SRC
mov di,OFFSET DEST
mov cx,LEN
rep movsb
; 2) Print DEST via DOS (AH=09h verwacht $-terminated DS:DX)
mov dx,OFFSET DEST
mov ah,9
int 21h
; 3) Exit
mov ax,4C00h
int 21h
; ----- Data -----
SRC db 'Assembler is leuk!$'
LEN equ $-SRC ; assemble-time: lengte in bytes van SRC
; ($ is de huidige locatie; $-SRC = afstand, dus aantal bytes.
; In dit voorbeeld inclusief de '$'-terminator → precies goed
; voor functie 09h en precies het aantal te kopiëren bytes.)
DEST db LEN dup(?) ; reserveer exact evenveel ruimte voor de kopie
; (vraagteken = oningevuld; we schrijven er zo in)
END START
Waarom LEN equ $-SRC essentieel is
- $ is de location counter van de assembler (niet van je programma tijdens runtime).
- $-SRC is een assemble-time berekening: het verschil tussen "nu" en het adres van SRC. Dat is exact het aantal bytes van de gedefinieerde data tot "nu" — hier dus de volledige string inclusief $.
- Met EQU maak je van die berekende waarde een constante. Dat getal wordt in de code geplaatst:
- in CX (zoveel bytes kopiëren)
- én in de declaratie van DEST (zoveel bytes reserveren).
Zonder voldoende gereserveerde doelruimte (DEST db LEN dup(?)) overschrijf je geheugen. In DOS is er geen bescherming: één fout en je slingert over je eigen data of zelfs DOS heen. Juist daarom is assemble-time lengteberekening zo’n krachtige (en veilige) gewoonte.
Korte epiloog (orde in de concepten)
- BIOS ≠ DOS: BIOS hoort bij de hardware (ROM), DOS is vervangbare software (IO.SYS + MSDOS.SYS + shell).
- Interrupts zijn de standaard interface: INT 21h voor DOS, INT 10h/16h/13h voor BIOS.
- Assembler-praktijk: correcte lengte en bufferreservering zijn net zo belangrijk als het juiste register.
Volgende keer ga ik met TASM de structuur verdiepen: CALL/RET, stackframes met BP, registers en flags netjes saven/restoren (PUSHF/POPF). En we bouwen een iets grotere routine met lussen en condities. Daarna heb je alles in handen om betrouwbare (en leesbare) ASM-utilities te schrijven en om ze later netjes te koppelen aan Pascal.
Gerelateerd
Turbo Assembler
Arnout van Kempen schrijft in deze rubriek over pret maken met computers. Hij gaat aan de slag met Pascal.
Pointers en dynamisch geheugen
Arnout van Kempen schrijft in deze rubriek over pret maken met computers. Hij gaat aan de slag met Pascal.
Geheugen en segmenten in real mode
Arnout van Kempen schrijft in deze rubriek over pret maken met computers. Hij gaat aan de slag met Pascal.
Modulariteit
Arnout van Kempen schrijft in deze rubriek over pret maken met computers. Hij gaat aan de slag met Pascal.
Errors en IOResult
Arnout van Kempen schrijft in deze rubriek over pret maken met computers. Hij gaat aan de slag met Pascal.
