The interrupt service Int 21/AH=02h is used to print the digits.
The standard conversion from number to numeral is performed with the div
instruction, the dividend is initially the highest power of ten fitting 16 bits (104) and it is reduced to lower powers at each iteration.
The parameters are shown in order of push.
Each one is 16 bits.
Parameter | Description |
---|---|
number | The 16-bit unsigned number to print in decimal |
show leading zeros | If 0 no non-significant zeros are printed, else they are. The number 0 is always printed as "0" |
push 241
push 0
call print_dec ;prints 241
push 56
push 1
call print_dec ;prints 00056
push 0
push 0
call print_dec ;prints 0
;Parameters (in order of push):
;
;number
;Show leading zeros
print_dec:
push bp
mov bp, sp
push ax
push bx
push cx
push dx
;Set up registers:
;AX = Number left to print
;BX = Power of ten to extract the current digit
;DX = Scratch/Needed for DIV
;CX = Scratch
mov ax, WORD PTR [bp+06h]
mov bx, 10000d
xor dx, dx
_pd_convert:
div bx ;DX = Number without highmost digit, AX = Highmost digit
mov cx, dx ;Number left to print
;If digit is non zero or param for leading zeros is non zero
;print the digit
or WORD PTR [bp+04h], ax
jnz _pd_print
;If both are zeros, make sure to show at least one digit so that 0 prints as "0"
cmp bx, 1
jne _pd_continue
_pd_print:
;Print digit in AL
mov dl, al
add dl, '0'
mov ah, 02h
int 21h
_pd_continue:
;BX = BX/10
;DX = 0
mov ax, bx
xor dx, dx
mov bx, 10d
div bx
mov bx, ax
;Put what's left of the number in AX again and repeat...
mov ax, cx
;...Until the divisor is zero
test bx, bx
jnz _pd_convert
pop dx
pop cx
pop bx
pop ax
pop bp
ret 04h
To port the code to NASM remove the PTR
keyword from memory accesses (e.g. mov ax, WORD PTR [bp+06h]
becomes mov ax, WORD [bp+06h]
)