Keyboard and screen with INT 21h

Programs talk to the user through DOS's INT 21h services. These five cover almost everything:

AHServiceInOut
1read a key, and show itAL = the key's code
2print a characterDL = its code
9print a stringDS:DX = its address, ending in $
0Ahread a lineDS:DX = a bufferthe buffer filled in
4Chend 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:

KeyCodeTo 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 MAIN

Input used: 34

Open in compiler

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 MAIN

Input used: Rahim

Open in compiler

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

1. The user types the key 9. What is in AL after INT 21h with AH = 1?
2. How do you print the number in BL (0 to 9) as a digit?
3. Which two codes make a new line?
4. After reading a line with AH = 0Ah into BUF, where is the number of characters typed?

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.