Function 09h writes the character in AL into CX cells starting at the cursor of page BH, each with attribute BL. It is the BIOS's way of putting colour on the screen: in text modes neither DOS output nor teletype (0Eh) sets the attribute. With CX above 1 it repeats the character along the line, and on into the next line past the right edge, which makes it handy for bars, frames and painting a stretch of the screen.

Two things surprise people. The cursor stays where it was, so the next write lands on top unless the cursor is moved with function 02h. And no character is special: 07h, 0Dh and 0Ah are drawn as the symbols of code page 437 instead of beeping or moving the cursor.

Prints "Stars: <- twenty, from the BIOS"; on the screen twenty yellow-on-red stars sit between the two parts.
MOV AH, 09h
MOV DX, OFFSET MSG1 ; "Stars: "
INT 21h
MOV AH, 03h ; the cursor: DH = row, DL = column
MOV BH, 0
INT 10h
PUSH DX ; where the stars start
MOV AX, 0900h + "*" ; AH = 09h, AL = the character
MOV BX, 004Eh ; BH = page 0, BL = 4Eh: yellow on red
MOV CX, 20 ; twenty of them
INT 10h ; the cursor stays put
POP DX
ADD DL, 21 ; past the stars and one blank
MOV AH, 02h ; move the cursor by hand
MOV BH, 0
INT 10h
MOV AH, 09h
MOV DX, OFFSET MSG2
INT 21h
MSG1 DB "Stars: $"
MSG2 DB "<- twenty, from the BIOS", 13, 10, "$"

Coloured text

To print a string in colour, write each character with 09h and CX = 1 to set the cell's colour, then the same character with 0Eh, which writes it again (keeping the attribute) and moves the cursor on, wrapping and scrolling as usual:

Prints "^ coloured with 09h, moved on with 0Eh"; on the screen the line above it reads "Light cyan, one character at a time" in light cyan.
MOV SI, OFFSET TXT1
CLD
NEXT1:
LODSB ; AL = next character
OR AL, AL ; 0 ends the text
JZ DONE1
MOV AH, 09h ; colour the cell at the cursor
MOV BX, 000Bh ; page 0, light cyan on black
MOV CX, 1
INT 10h
MOV AL, [SI-1] ; the character again: AL may not survive
MOV AH, 0Eh ; teletype: write it and move on
INT 10h
JMP NEXT1
DONE1:
MOV BH, 0 ; page 0
MOV AX, 0E0Dh ; BIOS teletype: CR...
INT 10h
MOV AX, 0E0Ah ; ...and LF: on to the next line
INT 10h
MOV AH, 09h
MOV DX, OFFSET MSG1
INT 21h
TXT1 DB "Light cyan, one character at a time", 0
MSG1 DB "^ coloured with 09h, moved on with 0Eh", 13, 10, "$"

Use this for short strings only: for CR and LF the pair would draw a symbol first. Function 13h writes a whole coloured string, control characters included, in one call.

Graphics modes

In graphics modes 09h draws the character from the BIOS font in colour BL. In the CGA and 16-colour modes, bit 7 of BL set means XOR: the dots are combined with what is there, so drawing the same character twice removes it again, the old way to show a moving marker. In mode 13h BL is simply one of the 256 colours.

Pitfalls

A large CX runs past the end of the page into whatever memory follows, possibly the next page. BH must be a page that exists in the mode. Writing to a page that is not shown works, but you will not see it until that page is selected.