Rewrite X2str functions to itoa/utoa ; it was a stupid idea to have seperate functions (=> more maintenance)
This commit is contained in:
439
src/convert.asm
439
src/convert.asm
@@ -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
|
||||
|
Reference in New Issue
Block a user