Programs talk to the user through DOS's INT 21h services. These five cover almost everything:
| AH | Service | In | Out |
|---|---|---|---|
| 1 | read a key, and show it | AL = the key's code | |
| 2 | print a character | DL = its code | |
| 9 | print a string | DS:DX = its address, ending in $ | |
| 0Ah | read a line | DS:DX = a buffer | the buffer filled in |
| 4Ch | end the program |
Services 7 and 8 read a key without showing it.
Characters are numbers
Every character has a code (ASCII). The digits '0' to '9' are 30h to 39h, so the key a user types is not yet the number it shows:
| Key | Code | To get the number |
|---|---|---|
'7' | 37h (55) | SUB AL, '0' (or SUB AL, 30H): 55 − 48 = 7 |
and to print a number from 0 to 9, add '0' back. A new line is two characters: carriage return 0Dh and line feed 0Ah.
; Read two digits and print their sum (the sum is at most 9).
.MODEL SMALL
.STACK 100H
.DATA
ASK DB 'Two digits: $'
SAY DB 0DH, 0AH, 'Sum: $'
.CODE
MAIN PROC
MOV AX, @DATA
MOV DS, AX
LEA DX, ASK
MOV AH, 9
INT 21H
MOV AH, 1 ; read the first digit
INT 21H
SUB AL, '0' ; '3' (33h) becomes 3
MOV BL, AL
MOV AH, 1 ; read the second digit
INT 21H
SUB AL, '0'
ADD BL, AL ; BL = the sum
LEA DX, SAY
MOV AH, 9
INT 21H
MOV DL, BL
ADD DL, '0' ; back to a digit's code
MOV AH, 2
INT 21H
MOV AH, 4CH
INT 21H
MAIN ENDP
END MAINInput used: 34
This example reads two digits. Its input is already filled in: in the visualizer, each character of the input box is one key, and a new line is Enter. Notice that DOS shows each key as it reads it with AH = 1, so the screen holds the typed digits as well as the answer. (In practice problems, only what your program prints is checked, not these echoed keys.)
Reading a whole line
Service 0Ah reads characters until Enter into a buffer you define like this:
BUF DB 20 ; byte 0: the most it may hold (Enter included)
DB ? ; byte 1: DOS writes how many were typed
DB 20 DUP(?) ; the characters, then 0Dh
; Read a line with service 0Ah, then print it back.
.MODEL SMALL
.STACK 100H
.DATA
ASK DB 'Your name: $'
HI DB 0DH, 0AH, 'Hello, $'
BUF DB 20, ?, 20 DUP(?) ; size, count, characters
.CODE
MAIN PROC
MOV AX, @DATA
MOV DS, AX
LEA DX, ASK
MOV AH, 9
INT 21H
LEA DX, BUF
MOV AH, 0AH ; read a line into BUF
INT 21H
MOV BL, BUF + 1 ; how many characters were typed
MOV BH, 0
MOV BUF[BX + 2], '$' ; end the text with $ for service 9
LEA DX, HI
MOV AH, 9
INT 21H
LEA DX, BUF + 2 ; the characters start at byte 2
MOV AH, 9
INT 21H
MOV AH, 4CH
INT 21H
MAIN ENDP
END MAINInput used: Rahim
The example puts a $ right after the characters (at BUF + 2 + count), so service 9 can print them back.
Common mistakes
- Printing the key's value as if it were the code: the number 7 prints as a strange symbol,
'7'is 37h. - Forgetting that AH = 1 puts the key in AL, then overwriting AL (or AH, by setting the next service number) before using it.
- Printing only 0Ah for a new line: the cursor goes down but not back to the start. Print 0Dh and 0Ah.
- Forgetting that byte 0 of an AH = 0Ah buffer must hold its size.
Quick check
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.