64bit itoa in assembly.
Posted: Wed Nov 17, 2010 2:36 pm
When writing my kernel i need to be able to debug properly, which means i need to be able to print out numbers on the screen. So i set about writing an itoa() function. Finding an itoa written in assembly is very difficult however. There are some implementations out there after some googling but they all seem unneccessarily long and complicated (and slower). And dissasembling HLL output is a complete mess.
So i decided to write my own, after realising that the basic algorithm is just to divide by the requested base repeatedly to get each of the numbers in reverse order i made this:
It works however only with base 10. I can't figure out how big the buffer needs to be mathematically. I could write a lookup table for this but there's got to be a mathematical way of finding it out. My maths doesn't extend very far past high school level, so it's very possibly it's the most obvious thing in the world.
I'm also aware I've also got problems that the ascii table doesn't go from '9' straight to 'a' or 'A' so some more code is needed there for bases higher than 10. That's pretty trivial to fix though.
Basically i'd like to know if anyone has or know where i could find a well documented/commented itoa implementation preferably written in assembly that i could look at.
So i decided to write my own, after realising that the basic algorithm is just to divide by the requested base repeatedly to get each of the numbers in reverse order i made this:
Code: Select all
; Int to Ascii
;
; Converts integer in rax into a string saved at buffer pointed to by rdi.
; Works by repeatedly dividing by base to get each number backwards and converting each to ascii.
;
; @param rax Integer to convert
; @param ebx base
; @param rdi pointer to buffer to save string to
;
; @return void
;
; @todo find out how big the buffer is going to need to be based on the base requested
io_itoa:
;find out how big the buffer needs to be for biggest number
;TODO
;divide by base repeatedly to get each number
mov ecx,20 ;maximum size the string could be (in base 10), this needs to be calculated
@@:
xor edx,edx ;clear rdx - clearing edx clears top half of rdx too, inconsistent with rest of architecture :/
div rbx ;divide by the requested base in ebx
add edx,'0' ;add ascii number for 0
mov byte[rdi+rcx-1],dl ;put numbers at end of buffer -> start of buffer
cmp eax,0 ;stop when the quotient is 0, no more numbers to convert
je @F
dec ecx
jnz @B
@@:
;shift number left
xor ebx,ebx
@@:
mov al,byte[rdi+rcx-1] ;load last byte that was written into al
mov byte[rdi+rcx-1],' ';clear where it came from
mov [rdi+rbx],al ;store start of buffer->end of buffer
inc ecx ;goto next byte written to by previous routine
inc ebx ;goto next byte from start
cmp ecx,21 ;needs to be one higher, not entirely sure why though.
jne @B
;null terminate
mov byte[rdi+rbx],0
ret
I'm also aware I've also got problems that the ascii table doesn't go from '9' straight to 'a' or 'A' so some more code is needed there for bases higher than 10. That's pretty trivial to fix though.
Basically i'd like to know if anyone has or know where i could find a well documented/commented itoa implementation preferably written in assembly that i could look at.