Rewrite X2str functions to itoa/utoa ; it was a stupid idea to have seperate functions (=> more maintenance)

This commit is contained in:
2025-07-15 07:58:18 +02:00
parent 954bc21eee
commit 9f33e36883
3 changed files with 223 additions and 359 deletions

View File

@@ -6,294 +6,225 @@ section .bss
cnvtBuff resb 67
cnvtBuffRev resb 67
section .text
global dec2str
global udec2str
global hex2str
global bin2str
global itoa
global utoa
;----- dec2str(int, padLen, bool padZeroes) -----;
; Converts a signed integer to a string (decimal output)
; Return value: Pointer to string containing the converted integer
;----- itoa(int, base, padLen, bool padZeroes) -----;
; Converts a signed integer to a string
; Return value: Pointer to converted string or 0(EOS) if entered base is invalid
; Supported bases: 10 (decimal)
; Used registers:
; rax* int stored for div >> (ret) pointer to cnvtBuff[]
; rcx* Counts length of created string
; rdx* (arg) padZeroes >> modulo as calculated by div >> character storage for cnvtBuff
; rdi* (arg) integer to convert to string >> Remembers if num is negative
; rsi* (arg) Padding length
; r8* Dividor for div
; r9* Points to cnvtBuff[]
; r10* padZeroes arg (since rdx used by DIV)
; r12 Remembers if number is negative
dec2str:
; rax* num to divide (DIV) >> Copy bytes when reversing string >> (ret) Pointer to converted string
; rdi* (arg) Integer to convert
; rsi* (arg) Base to convert to
; rdx* (arg) Padding length >> modulo (DIV)
; rcx* (arg) 0=pad spaces, otherwise pad zeroes >> Loop counter
; r9* Counts string length
; r10* Points to cnvtBuff(Rev)[]
; r11* Remembers if number is negative (r11b)
; r12 Stores (int)
; r13 Stores (base)
; r14 Stores (padLen)
; r15 Stores (padZeroes)
itoa:
; Before doing anything, check if base is valid
cmp rsi, 10
je .ok
xor rax, rax
ret
.ok:
push r12
xor r12, r12
mov r10, ' '
mov r9, '0'
test rdx, rdx
cmovnz r10, r9
lea r9, [rel cnvtBuffRev]
mov rax, rdi
xor dil, dil
xor rcx, rcx
push r13
push r14
push r15
; Store original arguments
mov r12, rdi
mov r13, rsi
mov r14, rdx
mov r15, rcx
; First, assure 0 <= padLen <= 64 ;(64, even though max signed int64 = 19 characters; enables to pad with base 2)
mov rdi, rdx
xor rsi, rsi
mov rdx, 64
call clamp
mov r14, rax
; Store padding character
mov rdi, ' '
mov rdx, '0'
test r15, r15
cmovnz rdi, rdx
mov r15, rdi
; Prepare for conversion
mov rax, r12
xor r9, r9
lea r10, [rel cnvtBuffRev]
; Check if negative
xor r11b, r11b
test rax, rax
jns .convert
mov r11b, 1
neg rax
mov dil, 1
.convert:
xor rdx, rdx
mov r8, 10
div r8
div r13
add rdx, '0'
mov [r9], dl
mov byte [r10], dl
inc r10
inc r9
inc rcx
test rax, rax
jnz .convert
test dil, dil
jz .makeString
mov r12, 1
; Adds '-' if needed
cmp r15, '0'
je .checkPadding ; If padding with zeroes, add minus sign before zeroes. Otherwise, add '-' and then add spaces
test r11b, r11b
jz .checkPadding
mov byte [r10], '-'
inc r10
inc r9
.checkPadding:
; Substract length of converted number from padLen
sub r14, r9
cmp r14, 0
jle .makeString
mov rcx, r14
.addPadding:
mov byte [r10], r15b
inc r10
inc r9
loop .addPadding
cmp r15, ' '
je .makeString
; Adds '-' if needed
test r11b, r11b
jz .makeString
mov byte [r10], '-'
inc r10
inc r9
.makeString:
sub rsi, rcx
cmp rsi, 0
jle .noPadding
mov r8, rcx
mov rdi, rsi
xor rsi, rsi
mov rdx, 64
call clamp
mov rcx, rax
test r12, r12
jz .paddingLoop
cmp r10, '0'
je .paddingLoop
mov byte [r9], '-'
inc r9
inc r8
xor r12, r12
.paddingLoop:
mov byte [r9], r10b
inc r9
inc r8
loop .paddingLoop
mov rcx, r8
.noPadding:
test r12, r12
jz .positive
mov [r9], byte '-'
inc r9
inc rcx
.positive:
dec r10 ;don't point to past last character
lea rdi, [rel cnvtBuff]
dec r9
mov rcx, r9
xor rax, rax
.makeStringLoop:
mov al, [r9]
mov [rdi], al
mov al, byte [r10]
mov byte [rdi], al
inc rdi
dec r9
dec r10
loop .makeStringLoop
mov byte [rdi], EOS
mov byte [rdi], EOS
.quit:
lea rax, [rel cnvtBuff]
pop r15
pop r14
pop r13
pop r12
ret
;----- udec2str(uint, padLen, bool padZeroes) -----;
; Converts an unsigned integer to a string (decimal output)
; Return value: Pointer to string containing the converted integer
; Used registers:
; rax* uint stored for div >> (ret) pointer to cnvtBuff[]
; rcx* Counts length of created string
; rdx* (arg) padZeroes >> modulo as calculated by div
; rdi* (arg) integer to convert to string
; rsi* (arg) padLen
; r8* Dividor for div
; r9* Points to cnvtBuff for writing characters
; r10* padZeroes arg (since rdx used by DIV)
udec2str:
mov r10, ' '
mov r9, '0'
test rdx, rdx
cmovnz r10, r9
lea r9, [rel cnvtBuffRev]
mov rax, rdi
xor rcx, rcx
.convert:
xor rdx, rdx
mov r8, 10
div r8
add rdx, '0'
mov [r9], dl
inc r9
inc rcx
test rax, rax
jnz .convert
sub rsi, rcx
cmp rsi, 0
jle .noPadding
mov r8, rcx
mov rdi, rsi
xor rsi, rsi
mov rdx, 64
call clamp
mov rcx, rax
.paddingLoop:
mov byte [r9], r10b
inc r9
inc r8
loop .paddingLoop
mov rcx, r8
.noPadding:
lea rdi, [rel cnvtBuff]
dec r9
.makeStringLoop:
mov al, [r9]
mov [rdi], al
inc rdi
dec r9
loop .makeStringLoop
mov byte [rdi], EOS
.quit:
lea rax, [rel cnvtBuff]
ret
;----- hex2str(uint, bool uppercase, padLen, bool padZeroes) -----;
; Converts an unsigned integer to a string (hexadecimal output)
; Return value: Pointer to string containing the converted integer
;----- utoa(int, base, padLen, bool padZeroes, bool upperCase) -----;
; Converts an unsigned integer to a string
; Return value: Pointer to converted string or 0(EOS) if entered base is invalid
; Supported bases: 2 (binary), 10 (decimal), 16 (hexadecimal)
; Used registers:
; rax* uint stored for div >> (ret) Pointer to cnvtBuff[]
; rdi (arg) Integer to convert
; rsi* (arg) 0=convert lowercase, (any other value)=convert uppercase >> Points to cnvtBuff for writing characters
; rdx* (arg) Padding length >> module as calculated by div
; rcx* (arg) padZeroes >> Counts length of created string
; r8* Dividor for div
; r9* Store arg rsi (uppercase)
; r10* Store arg rdx
; r11* Amount to add to number (for ASCII conversion, lowercase or uppercase)
; r12 Store arg padZeroes
hex2str:
; rax* num to divide (DIV) >> Copy bytes when reversing string >> (ret) Pointer to converted string
; rbx Stores (upperCase)
; rdi* (arg) Integer to convert
; rsi* (arg) Base to convert to
; rdx* (arg) Padding length >> modulo (DIV)
; rcx* (arg) 0=pad spaces, otherwise pad zeroes >> Loop counter
; r8* (arg) 0=lowercase letters (for bases using letters, ie 16), uppercase otherwise >> Stores character to copy to when determining number or uppercase/lowercase letter
; r9* Counts string length
; r10* Points to cnvtBuff(Rev)[]
; r11* Remembers if number is negative (r11b)
; r12 Stores (int)
; r13 Stores (base)
; r14 Stores (padLen)
; r15 Stores (padZeroes)
utoa:
; Before doing anything, check if base is valid
cmp rsi, 2
je .ok
cmp rsi, 10
je .ok
cmp rsi, 16
je .ok
xor rax, rax
ret
.ok:
push rbx
push r12
mov r9, rsi
mov r10, rdx
mov r12, ' '
mov rsi, '0'
test rcx, rcx
cmovnz r12, rsi
lea rsi, [rel cnvtBuffRev]
mov rax, rdi
xor rcx, rcx
mov r8, 87
test r9, r9
cmovz r11, r8
test r9, r9
push r13
push r14
push r15
; Store original arguments
mov rbx, r8
mov r12, rdi
mov r13, rsi
mov r14, rdx
mov r15, rcx
; First, assure 0 <= padLen <= 64 ;(64, even though max signed int64 = 19 characters; enables to pad with base 2)
mov rdi, rdx
xor rsi, rsi
mov rdx, 64
call clamp
mov r14, rax
; Store padding character
mov rdi, ' '
mov rdx, '0'
test r15, r15
cmovnz rdi, rdx
mov r15, rdi
; Prepare for conversion
mov rax, r12
xor r9, r9
lea r10, [rel cnvtBuffRev]
mov rdx, 'a'-10
test rbx, rbx
cmovz r8, rdx
jz .convert
mov r11, 55
mov r8, 'A'-10
.convert:
xor rdx, rdx
mov r8, 16
div r8
cmp rdx, 10
jb .num
add rdx, r11
jmp .push
.num:
add rdx, '0'
.push:
mov [rsi], dl
inc rsi
inc rcx
div r13
cmp dl, 9
jle .noLetter
add dl, r8b
jmp .write
.noLetter:
add dl, '0'
.write:
mov byte [r10], dl
inc r10
inc r9
test rax, rax
jnz .convert
sub r10, rcx
cmp r10, 0
jle .noPadding
mov r8, rcx
push rsi
mov rdi, r10
xor rsi, rsi
mov rdx, 64
call clamp
pop rsi
mov rcx, rax
.paddingLoop:
mov byte[rsi], r12b
inc rsi
inc r8
loop .paddingLoop
mov rcx, r8
.noPadding:
dec rsi
lea rdi, [rel cnvtBuff]
.checkPadding:
; Substract length of converted number from padLen
sub r14, r9
cmp r14, 0
jle .makeString
mov rcx, r14
.addPadding:
mov byte [r10], r15b
inc r10
inc r9
loop .addPadding
.makeString:
mov al, [rsi]
mov [rdi], al
inc rdi
dec rsi
loop .makeString
mov byte [rdi], EOS
.quit:
lea rax, [rel cnvtBuff]
pop r12
ret
;----- bin2str(uint, padLen, bool padZeroes) -----;
; Converts an unsigned integer to a string (binary output)
; Return value: Pointer to string containing the converted integer
; Used registers:
; rax* uint stored for div >> (ret) pointer to cnvtBuff[]
; rcx* Counts length of created string
; rdx* (arg) If padLen>0, use Zeroes (rdx!=0) or spaces (rdx=0) >> modulo as calculated by div >> character storage for cnvtBuff
; rdi* (arg) integer to convert to string
; rsi* (arg) Padding length
; r8* Dividor for div
; r9* Points to cnvtBuff for writing characters
; r10* padZeroes arg (since rdx used by DIV)
bin2str:
mov r10, ' '
mov r9, '0'
test rdx, rdx
cmovnz r10, r9
lea r9, [rel cnvtBuffRev]
mov rax, rdi
xor rcx, rcx
.convert:
xor rdx, rdx
mov r8, 2
div r8
add rdx, '0'
mov [r9], dl
inc r9
inc rcx
test rax, rax
jnz .convert
sub rsi, rcx
cmp rsi, 0
jle .noPadding
mov r8, rcx
mov rdi, rsi
xor rsi, rsi
mov rdx, 64
call clamp
mov rcx, rax
.paddingLoop:
mov byte [r9], r10b
inc r9
inc r8
loop .paddingLoop
mov rcx, r8
.noPadding:
dec r9
dec r10 ;don't point to past last character
lea rdi, [rel cnvtBuff]
mov rcx, r9
xor rax, rax
.makeStringLoop:
mov al, [r9]
mov [rdi], al
mov al, byte [r10]
mov byte [rdi], al
inc rdi
dec r9
dec r10
loop .makeStringLoop
mov byte [rdi], EOS
mov byte [rdi], EOS
.quit:
pop r15
pop r14
pop r13
pop r12
pop rbx
lea rax, [rel cnvtBuff]
ret