I know this is one of the most trivial things to implement in a high level language. In C it goes like this:
void print_integer(unsigned int x)
{
if ((x / 10) != 0) pi(x / 10);
putch((x % 10) + ‘0’);
}
The annoying thing is that you have to div twice and do a modulo once. Which in reality can be merged into a single X86 instruction. Another thing is that if you want to be able to print a normal result for an input of 0 you will have to test the result of the division instead of checking simply x itself. The conversion is done from the least significant digit to the most. But when we display the result (or put it in a buffer) we have to reverse it. Therefore the recursion is so handy here. This is my go in 16bit, it’s a code that I wrote a few years ago, and I just decided I should put it here for a reference. I have to admit that I happened to use this same code for also 32bits or even different processors and since it’s so elegant it works so well and easy to port. But I leave it for you to judge ;)
bits 16
mov ax, 12345
call print_integer
xor ax, ax
call print_integer
ret
print_integer:
; base 10
push byte 10
pop bx
.next:; make a 32 bits division, remainder in dx, quotient in ax
xor dx, dx
div bx
push dx ; push remainder
or ax, ax ; if the result if 0, we will stop recursing
jz .stop
call .next ; now this is the coolest twist ever, the IP that is pushed onto the stack…
.stop:
pop ax ; get the remainder (in reversed order)
add al, 0x30 ; convert it to a character
int 0x29 ; use (what used to be an undocumented) interrupt to print al
ret ; go back to ‘stop’ and read the next digit…
I urge you to compile the C code with full optimization and compare the codes for yourself.
print_integer:
aam
call .next
.next
xchg ah, al
add al, ‘0’
int 0x29
ret
Ofc Peter :) but now its input is a byte rather than a word(/dword)… it’s cute nevertheless
Though it seems you missed a few lines…oi?
It just needs a push/pop. Here’s the whole thing:
mov ax, 12345
call print_integer
xor ax, ax
call print_integer
ret
print_integer:
push ax
xchg ah, al
call .next1
pop ax
.next1:
aam
call .next2
.next2:
xchg ah, al
add al, 0x30
int 0x29
ret