printf: Add padding support for %d, %i, %u, %x, %X
This commit is contained in:
@@ -71,6 +71,8 @@ puts:
|
|||||||
; %X Unsigned integer, printed as hexadecimal number (uppercase)
|
; %X Unsigned integer, printed as hexadecimal number (uppercase)
|
||||||
; %b Unsigned integer, printed as binary number
|
; %b Unsigned integer, printed as binary number
|
||||||
; %s String
|
; %s String
|
||||||
|
; %N* Pad left, N chars (maximum 64). Supported *: d, i, u, x, X, b
|
||||||
|
; *0N* Pad left with zeroes, N chars (maximum 64). Supported *: d, i, u, x, X, b
|
||||||
; <!> Unsupported specifiers are printed as-is
|
; <!> Unsupported specifiers are printed as-is
|
||||||
; <!> For all specifiers (except %%) an argument is expected. Mismatch between arguments given and specifiers provided will lead to issues
|
; <!> For all specifiers (except %%) an argument is expected. Mismatch between arguments given and specifiers provided will lead to issues
|
||||||
; Used registers:
|
; Used registers:
|
||||||
@@ -236,13 +238,16 @@ printf:
|
|||||||
.rep_d:
|
.rep_d:
|
||||||
load_arg rsi
|
load_arg rsi
|
||||||
push_regs
|
push_regs
|
||||||
|
mov rdx, r13
|
||||||
cmp byte [rdi + 1], 'u'
|
cmp byte [rdi + 1], 'u'
|
||||||
je .callUINT2STR
|
je .callUINT2STR
|
||||||
mov rdi, rsi
|
mov rdi, rsi
|
||||||
|
mov rsi, r12
|
||||||
call dec2str
|
call dec2str
|
||||||
jmp .loadConvertedStr
|
jmp .loadConvertedStr
|
||||||
.callUINT2STR:
|
.callUINT2STR:
|
||||||
mov rdi, rsi
|
mov rdi, rsi
|
||||||
|
mov rsi, r12
|
||||||
call udec2str
|
call udec2str
|
||||||
.loadConvertedStr:
|
.loadConvertedStr:
|
||||||
mov rsi, rax
|
mov rsi, rax
|
||||||
@@ -261,8 +266,12 @@ printf:
|
|||||||
push rax
|
push rax
|
||||||
push rdx
|
push rdx
|
||||||
push r9
|
push r9
|
||||||
|
push r10
|
||||||
|
mov rdx, r12
|
||||||
|
mov rcx, r13
|
||||||
call hex2str
|
call hex2str
|
||||||
mov rsi, rax
|
mov rsi, rax
|
||||||
|
pop r10
|
||||||
pop r9
|
pop r9
|
||||||
pop rdx
|
pop rdx
|
||||||
pop rax
|
pop rax
|
||||||
|
168
src/convert.asm
168
src/convert.asm
@@ -11,26 +11,27 @@ section .text
|
|||||||
global hex2str
|
global hex2str
|
||||||
global bin2str
|
global bin2str
|
||||||
|
|
||||||
;----- dec2str(int) -----;
|
;----- dec2str(int, padLen, bool padZeroes) -----;
|
||||||
; Converts a signed integer to a string (decimal output)
|
; Converts a signed integer to a string (decimal output)
|
||||||
; Return value: Pointer to string containing the converted integer
|
; Return value: Pointer to string containing the converted integer
|
||||||
; Used registers:
|
; Used registers:
|
||||||
; rax* int stored for div >> (ret) pointer to cnvtBuff[]
|
; rax* int stored for div >> (ret) pointer to cnvtBuff[]
|
||||||
; rcx* Counts length of created string
|
; rcx* Counts length of created string
|
||||||
; rdx* modulo as calculated by div >> character storage for cnvtBuff
|
; rdx* (arg) padZeroes >> modulo as calculated by div >> character storage for cnvtBuff
|
||||||
; rdi* (arg) integer to convert to string >> Remembers if num is negative
|
; rdi* (arg) integer to convert to string >> Remembers if num is negative
|
||||||
; rsi* Points to cnvtBuff for writing characters
|
; rsi* (arg) Padding length
|
||||||
; r8* Dividor for div
|
; r8* Dividor for div
|
||||||
|
; r9* Points to cnvtBuff[]
|
||||||
|
; r10* padZeroes arg (since rdx used by DIV)
|
||||||
|
; r12 Remembers if number is negative
|
||||||
dec2str:
|
dec2str:
|
||||||
lea rsi, [rel cnvtBuffRev]
|
push r12
|
||||||
test rdi, rdi
|
xor r12, r12
|
||||||
jnz .notZero
|
mov r10, ' '
|
||||||
lea rsi, [rel cnvtBuff]
|
mov r9, '0'
|
||||||
mov byte [rsi], '0'
|
test rdx, rdx
|
||||||
mov byte [rsi+1], EOS
|
cmovnz r10, r9
|
||||||
jmp .quit
|
lea r9, [rel cnvtBuffRev]
|
||||||
|
|
||||||
.notZero:
|
|
||||||
mov rax, rdi
|
mov rax, rdi
|
||||||
xor dil, dil
|
xor dil, dil
|
||||||
xor rcx, rcx
|
xor rcx, rcx
|
||||||
@@ -43,51 +44,78 @@ dec2str:
|
|||||||
mov r8, 10
|
mov r8, 10
|
||||||
div r8
|
div r8
|
||||||
add rdx, '0'
|
add rdx, '0'
|
||||||
mov [rsi], dl
|
mov [r9], dl
|
||||||
inc rsi
|
inc r9
|
||||||
inc rcx
|
inc rcx
|
||||||
test rax, rax
|
test rax, rax
|
||||||
jnz .convert
|
jnz .convert
|
||||||
test dil, dil
|
test dil, dil
|
||||||
jz .makeString
|
jz .makeString
|
||||||
mov [rsi], byte '-'
|
mov r12, 1
|
||||||
inc rcx
|
|
||||||
inc rsi
|
|
||||||
.makeString:
|
.makeString:
|
||||||
|
sub rsi, rcx
|
||||||
|
cmp rsi, rcx
|
||||||
|
jl .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:
|
||||||
lea rdi, [rel cnvtBuff]
|
lea rdi, [rel cnvtBuff]
|
||||||
dec rsi
|
dec r9
|
||||||
.makeStringLoop:
|
.makeStringLoop:
|
||||||
mov al, [rsi]
|
mov al, [r9]
|
||||||
mov [rdi], al
|
mov [rdi], al
|
||||||
inc rdi
|
inc rdi
|
||||||
dec rsi
|
dec r9
|
||||||
loop .makeStringLoop
|
loop .makeStringLoop
|
||||||
mov byte [rdi], EOS
|
mov byte [rdi], EOS
|
||||||
|
|
||||||
.quit:
|
.quit:
|
||||||
lea rax, [rel cnvtBuff]
|
lea rax, [rel cnvtBuff]
|
||||||
|
pop r12
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;----- udec2str(uint) -----;
|
;----- udec2str(uint, padLen, bool padZeroes) -----;
|
||||||
; Converts an unsigned integer to a string (decimal output)
|
; Converts an unsigned integer to a string (decimal output)
|
||||||
; Return value: Pointer to string containing the converted integer
|
; Return value: Pointer to string containing the converted integer
|
||||||
; Used registers:
|
; Used registers:
|
||||||
; rax* uint stored for div >> (ret) pointer to cnvtBuff[]
|
; rax* uint stored for div >> (ret) pointer to cnvtBuff[]
|
||||||
; rcx* Counts length of created string
|
; rcx* Counts length of created string
|
||||||
; rdx* modulo as calculated by div >> character storage for cnvtBuff
|
; rdx* (arg) padZeroes >> modulo as calculated by div
|
||||||
; rdi* (arg) integer to convert to string
|
; rdi* (arg) integer to convert to string
|
||||||
; rsi* Points to cnvtBuff for writing characters
|
; rsi* (arg) padLen
|
||||||
; r8* Dividor for div
|
; r8* Dividor for div
|
||||||
|
; r9* Points to cnvtBuff for writing characters
|
||||||
|
; r10* padZeroes arg (since rdx used by DIV)
|
||||||
udec2str:
|
udec2str:
|
||||||
lea rsi, [rel cnvtBuffRev]
|
mov r10, ' '
|
||||||
test rdi, rdi
|
mov r9, '0'
|
||||||
jnz .notZero
|
test rdx, rdx
|
||||||
lea rsi, [rel cnvtBuff]
|
cmovnz r10, r9
|
||||||
mov byte [rsi], '0'
|
lea r9, [rel cnvtBuffRev]
|
||||||
mov byte [rsi+1], EOS
|
|
||||||
jmp .quit
|
|
||||||
|
|
||||||
.notZero:
|
|
||||||
mov rax, rdi
|
mov rax, rdi
|
||||||
xor rcx, rcx
|
xor rcx, rcx
|
||||||
.convert:
|
.convert:
|
||||||
@@ -95,18 +123,34 @@ udec2str:
|
|||||||
mov r8, 10
|
mov r8, 10
|
||||||
div r8
|
div r8
|
||||||
add rdx, '0'
|
add rdx, '0'
|
||||||
mov [rsi], dl
|
mov [r9], dl
|
||||||
inc rsi
|
inc r9
|
||||||
inc rcx
|
inc rcx
|
||||||
test rax, rax
|
test rax, rax
|
||||||
jnz .convert
|
jnz .convert
|
||||||
|
sub rsi, rcx
|
||||||
|
cmp rsi, rcx
|
||||||
|
jl .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]
|
lea rdi, [rel cnvtBuff]
|
||||||
dec rsi
|
dec r9
|
||||||
.makeStringLoop:
|
.makeStringLoop:
|
||||||
mov al, [rsi]
|
mov al, [r9]
|
||||||
mov [rdi], al
|
mov [rdi], al
|
||||||
inc rdi
|
inc rdi
|
||||||
dec rsi
|
dec r9
|
||||||
loop .makeStringLoop
|
loop .makeStringLoop
|
||||||
mov byte [rdi], EOS
|
mov byte [rdi], EOS
|
||||||
|
|
||||||
@@ -114,33 +158,31 @@ udec2str:
|
|||||||
lea rax, [rel cnvtBuff]
|
lea rax, [rel cnvtBuff]
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;----- hex2str(uint, bool uppercase) -----;
|
;----- hex2str(uint, bool uppercase, padLen, bool padZeroes) -----;
|
||||||
; Converts an unsigned integer to a string (hexadecimal output)
|
; Converts an unsigned integer to a string (hexadecimal output)
|
||||||
; Return value: Pointer to string containing the converted integer
|
; Return value: Pointer to string containing the converted integer
|
||||||
; Used registers:
|
; Used registers:
|
||||||
; rax* uint stored for div >> (ret) Pointer to cnvtBuff[]
|
; rax* uint stored for div >> (ret) Pointer to cnvtBuff[]
|
||||||
; rdi (arg) Integer to convert
|
; rdi (arg) Integer to convert
|
||||||
; rsi* (arg) 0=convert lowercase, (any other value)=convert uppercase >> Points to cnvtBuff for writing characters
|
; rsi* (arg) 0=convert lowercase, (any other value)=convert uppercase >> Points to cnvtBuff for writing characters
|
||||||
; rdx* module as calculated by div
|
; rdx* (arg) Padding length >> module as calculated by div
|
||||||
; rcx* Counts length of created string
|
; rcx* (arg) padZeroes >> Counts length of created string
|
||||||
; r8* Dividor for div
|
; r8* Dividor for div
|
||||||
; r9* Store arg rsi (uppercase)
|
; r9* Store arg rsi (uppercase)
|
||||||
|
; r10* Store arg rdx
|
||||||
; r11* Amount to add to number (for ASCII conversion, lowercase or uppercase)
|
; r11* Amount to add to number (for ASCII conversion, lowercase or uppercase)
|
||||||
|
; r12 Store arg padZeroes
|
||||||
hex2str:
|
hex2str:
|
||||||
|
push r12
|
||||||
mov r9, rsi
|
mov r9, rsi
|
||||||
|
mov r10, rdx
|
||||||
|
mov r12, ' '
|
||||||
|
mov rsi, '0'
|
||||||
|
test rcx, rcx
|
||||||
|
cmovnz r12, rsi
|
||||||
lea rsi, [rel cnvtBuffRev]
|
lea rsi, [rel cnvtBuffRev]
|
||||||
test rdi, rdi
|
|
||||||
jnz .notZero
|
|
||||||
lea rsi, [rel cnvtBuff]
|
|
||||||
mov word [rsi], '0x'
|
|
||||||
mov byte [rsi + 2], '0'
|
|
||||||
mov byte [rsi + 3], EOS
|
|
||||||
jmp .quit
|
|
||||||
|
|
||||||
.notZero:
|
|
||||||
mov rax, rdi
|
mov rax, rdi
|
||||||
xor rcx, rcx
|
xor rcx, rcx
|
||||||
|
|
||||||
mov r8, 87
|
mov r8, 87
|
||||||
test r9, r9
|
test r9, r9
|
||||||
cmovz r11, r8
|
cmovz r11, r8
|
||||||
@@ -163,10 +205,25 @@ hex2str:
|
|||||||
inc rcx
|
inc rcx
|
||||||
test rax, rax
|
test rax, rax
|
||||||
jnz .convert
|
jnz .convert
|
||||||
|
sub r10, rcx
|
||||||
mov word [rsi], 'x0'
|
cmp r10, rcx
|
||||||
|
jl .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 rsi
|
||||||
add rcx, 2
|
inc r8
|
||||||
|
loop .paddingLoop
|
||||||
|
mov rcx, r8
|
||||||
|
.noPadding:
|
||||||
|
dec rsi
|
||||||
lea rdi, [rel cnvtBuff]
|
lea rdi, [rel cnvtBuff]
|
||||||
.makeString:
|
.makeString:
|
||||||
mov al, [rsi]
|
mov al, [rsi]
|
||||||
@@ -178,6 +235,7 @@ hex2str:
|
|||||||
|
|
||||||
.quit:
|
.quit:
|
||||||
lea rax, [rel cnvtBuff]
|
lea rax, [rel cnvtBuff]
|
||||||
|
pop r12
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;----- bin2str(uint, padLen, bool padZeroes) -----;
|
;----- bin2str(uint, padLen, bool padZeroes) -----;
|
||||||
@@ -223,14 +281,10 @@ bin2str:
|
|||||||
cmp rsi, rcx
|
cmp rsi, rcx
|
||||||
jl .noPadding
|
jl .noPadding
|
||||||
mov r8, rcx
|
mov r8, rcx
|
||||||
push rsi
|
|
||||||
push rdx
|
|
||||||
mov rdi, rsi
|
mov rdi, rsi
|
||||||
xor rsi, rsi
|
xor rsi, rsi
|
||||||
mov rdx, 64
|
mov rdx, 64
|
||||||
call clamp
|
call clamp
|
||||||
pop rdx
|
|
||||||
pop rsi
|
|
||||||
mov rcx, rax
|
mov rcx, rax
|
||||||
.paddingLoop:
|
.paddingLoop:
|
||||||
mov byte [r9], r10b
|
mov byte [r9], r10b
|
||||||
|
@@ -92,6 +92,16 @@ section .rodata
|
|||||||
printf5Str db "%x|%X , %x|%X",NL,EOS
|
printf5Str db "%x|%X , %x|%X",NL,EOS
|
||||||
printf6 db TAB,"printf(",DQUO,"%b | %8b | %08b\n",DQUO,", 5, 5, 5): ",NL,TAB,TAB,EOS
|
printf6 db TAB,"printf(",DQUO,"%b | %8b | %08b\n",DQUO,", 5, 5, 5): ",NL,TAB,TAB,EOS
|
||||||
printf6Str db "%b | %8b | %08b",NL,EOS
|
printf6Str db "%b | %8b | %08b",NL,EOS
|
||||||
|
printf7 db TAB,"printf(",DQUO,"%d | %8d | %08d\n",DQUO,", -234, -234, -234): ",NL,TAB,TAB,EOS
|
||||||
|
printf7Str db "%d | %8d | %08d",NL,EOS
|
||||||
|
printf8 db TAB,"printf(",DQUO,"%i | %8i | %08i\n",DQUO,", -234, -234, -234): ",NL,TAB,TAB,EOS
|
||||||
|
printf8Str db "%i | %8i | %08i",NL,EOS
|
||||||
|
printf9 db TAB,"printf(",DQUO,"%u | %8u | %08u\n",DQUO,", -234, -234, -234): ",NL,TAB,TAB,EOS
|
||||||
|
printf9Str db "%u | %8u | %08u",NL,EOS
|
||||||
|
printf10 db TAB,"printf(",DQUO,"%x | %8x | %08x\n",DQUO,", 0xAB0F, -0xAB0F, 0xAB0F): ",NL,TAB,TAB,EOS
|
||||||
|
printf10Str db "%x | %8x | %08x",NL,EOS
|
||||||
|
printf11 db TAB,"printf(",DQUO,"%X | %8X | %08X\n",DQUO,", 0xAB0F, -0xAB0F, 0xAB0F): ",NL,TAB,TAB,EOS
|
||||||
|
printf11Str db "%X | %8X | %08X",NL,EOS
|
||||||
|
|
||||||
; strlen()
|
; strlen()
|
||||||
msgStrlen db NL,"TEST strlen()",NL,EOS
|
msgStrlen db NL,"TEST strlen()",NL,EOS
|
||||||
@@ -350,6 +360,51 @@ _start:
|
|||||||
mov rdx, 5
|
mov rdx, 5
|
||||||
mov rcx, 5
|
mov rcx, 5
|
||||||
call printf
|
call printf
|
||||||
|
|
||||||
|
; TEST 7
|
||||||
|
lea rdi, [rel printf7]
|
||||||
|
call print
|
||||||
|
lea rdi, [rel printf7Str]
|
||||||
|
mov rsi, -234
|
||||||
|
mov rdx, -234
|
||||||
|
mov rcx, -234
|
||||||
|
call printf
|
||||||
|
|
||||||
|
; TEST 8
|
||||||
|
lea rdi, [rel printf8]
|
||||||
|
call print
|
||||||
|
lea rdi, [rel printf8Str]
|
||||||
|
mov rsi, -234
|
||||||
|
mov rdx, -234
|
||||||
|
mov rcx, -234
|
||||||
|
call printf
|
||||||
|
|
||||||
|
; TEST 9
|
||||||
|
lea rdi, [rel printf9]
|
||||||
|
call print
|
||||||
|
lea rdi, [rel printf9Str]
|
||||||
|
mov rsi, -234
|
||||||
|
mov rdx, -234
|
||||||
|
mov rcx, -234
|
||||||
|
call printf
|
||||||
|
|
||||||
|
; TEST 10
|
||||||
|
lea rdi, [rel printf10]
|
||||||
|
call print
|
||||||
|
lea rdi, [rel printf10Str]
|
||||||
|
mov rsi, 0xAB0F
|
||||||
|
mov rdx, 0xAB0F
|
||||||
|
mov rcx, 0xAB0F
|
||||||
|
call printf
|
||||||
|
|
||||||
|
; TEST 11
|
||||||
|
lea rdi, [rel printf11]
|
||||||
|
call print
|
||||||
|
lea rdi, [rel printf11Str]
|
||||||
|
mov rsi, 0xAB0F
|
||||||
|
mov rdx, 0xAB0F
|
||||||
|
mov rcx, 0xAB0F
|
||||||
|
call printf
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
;---
|
;---
|
||||||
|
Reference in New Issue
Block a user