This gem takes a double word (DX:AX
) and converts a base 10 number that can be displayed on the CRT. The basic algorithm is division by 10 and save the remainder.;
; converting DX:AX into a base 10 string
;
; input:
; dx:ax = double word number
; di = output puffer
;
; output:
; di = after end of converted buffer
;
; destroys:
; ax,dx
; flags
;
disp10: push bx
push cx
push si
mov si,dx ; Save high word in SI as well
mov bx,10 ; Divisor
mov cx,sp ; Remember stack location
big:
cmp dx,bx ; Will the division fit in 16 bits?
jb small ; Yes, DX < BX, so the result will fit in AX!
xchg ax,si ; High word in AX, save low word in SI
xor dx,dx ; zero-extend into DX
div bx ; Divide upper 16 bits, remainder ends up in DX
xchg ax,si ; Swap back
div bx ; Divide lower half
push dx ; Save remainder (0..9) on the stack!
mov dx,si ; prepare for next round
jmp big
small: ; Remainder fits in lower 16 bits (AX)
div bx ; Divide, result stays in AX, remainder in DX
push dx ; Save remainder
xor dx,dx ; Prepare for next round
test ax,ax ; Any more digits?
jnz small
; All the digits are collected on the stack, now store them in order:
store:
pop ax
add al,'0'
mov [di],al
inc di
cmp cx,sp
jne store
pop si
pop cx
pop bx
ret
The key here is that regardless of how long the number to be divided is, the division can be performed in steps, and the DIV opcode puts the result and remainder in the right registers for this. The only problem is the possibility of overflowing the stack. The string is however not that long so it should not pose as a real problem.