global I2A
section .text
; =============================================================================================
; int I2A (unsigned Value, char *Destination)
; Converts unsigned value to uppercase ASCII string minus leading zeros.
; At minimum character "0" is returned.
; ENTER: ARG1 = 64 bit value to be converted.
; ARG2 = Pointer to destination ASCII buffer.
; LEAVE: RAX = Length of output excluding terminating character.
; NOTE: Caller should assure destination is large enough being a maximum of 17 characters.
; ---------------------------------------------------------------------------------------------
I2A enter 24, 0 ; Only 17 required, keeps stack qword aligned.
push rdi ; Preserve
mov rdi, rbp ; Top of frame
std ; Auto decrement
mov al, 0
stosb ; Post terminating charcter
xor rcx, rcx ; Set counter register to zero
mov rdx, [rbp + 16] ; Get value to be converted
; Cycle through value until all bits are shifted out.
.L0 mov al, dl ; Copy low order bits
and al, 15 ; Mask out high nibble
cmp al, 10
jb .Dec
; It is A - F
sub al, 9
or al, 64
jmp .Dec + 2
; It is 0 - 9
.Dec or al, 48
; Write to destination, increment character count and see if RDX is null yet
stosb
inc rcx
shr rdx, 4 ; Shift next nibble into low order bits
jnz .L0
; Value has been converted, now move to destination depicted by ARG2
push rsi ; Preserve
mov rsi, rdi ; Proc destination now becomes source
inc rsi ; Bump to actual first character
mov rdi, [rbp + 24] ; Get pointer to destination
cld ; Reset to auto increment
push rcx ; We'll need this value to return to caller
inc rcx ; So terminating character is included
rep movsb
; Postamble, move character count into RAX and restore RSI & RDI
pop rax ; Character count into RAX
pop rsi
pop rdi
leave ; Kill procedure frame
ret 16 ; Waster callers arguments