printf: Add padding support for %d, %i, %u, %x, %X

This commit is contained in:
2025-07-12 16:33:07 +02:00
parent b327248e0c
commit efeded5547
3 changed files with 176 additions and 58 deletions

View File

@@ -71,6 +71,8 @@ puts:
; %X Unsigned integer, printed as hexadecimal number (uppercase)
; %b Unsigned integer, printed as binary number
; %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
; <!> For all specifiers (except %%) an argument is expected. Mismatch between arguments given and specifiers provided will lead to issues
; Used registers:
@@ -236,13 +238,16 @@ printf:
.rep_d:
load_arg rsi
push_regs
mov rdx, r13
cmp byte [rdi + 1], 'u'
je .callUINT2STR
mov rdi, rsi
mov rsi, r12
call dec2str
jmp .loadConvertedStr
.callUINT2STR:
mov rdi, rsi
mov rsi, r12
call udec2str
.loadConvertedStr:
mov rsi, rax
@@ -261,8 +266,12 @@ printf:
push rax
push rdx
push r9
push r10
mov rdx, r12
mov rcx, r13
call hex2str
mov rsi, rax
pop r10
pop r9
pop rdx
pop rax

View File

@@ -11,26 +11,27 @@ section .text
global hex2str
global bin2str
;----- dec2str(int) -----;
;----- dec2str(int, padLen, bool padZeroes) -----;
; Converts a signed integer to a string (decimal output)
; Return value: Pointer to string containing the converted integer
; Used registers:
; rax* int stored for div >> (ret) pointer to cnvtBuff[]
; 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
; rsi* Points to cnvtBuff for writing characters
; 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:
lea rsi, [rel cnvtBuffRev]
test rdi, rdi
jnz .notZero
lea rsi, [rel cnvtBuff]
mov byte [rsi], '0'
mov byte [rsi+1], EOS
jmp .quit
.notZero:
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
@@ -43,51 +44,78 @@ dec2str:
mov r8, 10
div r8
add rdx, '0'
mov [rsi], dl
inc rsi
mov [r9], dl
inc r9
inc rcx
test rax, rax
jnz .convert
test dil, dil
jz .makeString
mov [rsi], byte '-'
inc rcx
inc rsi
mov r12, 1
.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]
dec rsi
dec r9
.makeStringLoop:
mov al, [rsi]
mov al, [r9]
mov [rdi], al
inc rdi
dec rsi
dec r9
loop .makeStringLoop
mov byte [rdi], EOS
.quit:
lea rax, [rel cnvtBuff]
pop r12
ret
;----- udec2str(uint) -----;
;----- 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* modulo as calculated by div >> character storage for cnvtBuff
; rdx* (arg) padZeroes >> modulo as calculated by div
; rdi* (arg) integer to convert to string
; rsi* Points to cnvtBuff for writing characters
; rsi* (arg) padLen
; r8* Dividor for div
; r9* Points to cnvtBuff for writing characters
; r10* padZeroes arg (since rdx used by DIV)
udec2str:
lea rsi, [rel cnvtBuffRev]
test rdi, rdi
jnz .notZero
lea rsi, [rel cnvtBuff]
mov byte [rsi], '0'
mov byte [rsi+1], EOS
jmp .quit
.notZero:
mov r10, ' '
mov r9, '0'
test rdx, rdx
cmovnz r10, r9
lea r9, [rel cnvtBuffRev]
mov rax, rdi
xor rcx, rcx
.convert:
@@ -95,18 +123,34 @@ udec2str:
mov r8, 10
div r8
add rdx, '0'
mov [rsi], dl
inc rsi
mov [r9], dl
inc r9
inc rcx
test rax, rax
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]
dec rsi
dec r9
.makeStringLoop:
mov al, [rsi]
mov al, [r9]
mov [rdi], al
inc rdi
dec rsi
dec r9
loop .makeStringLoop
mov byte [rdi], EOS
@@ -114,33 +158,31 @@ udec2str:
lea rax, [rel cnvtBuff]
ret
;----- hex2str(uint, bool uppercase) -----;
;----- 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
; 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* module as calculated by div
; rcx* Counts length of created string
; 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:
push r12
mov r9, rsi
mov r10, rdx
mov r12, ' '
mov rsi, '0'
test rcx, rcx
cmovnz r12, rsi
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
xor rcx, rcx
mov r8, 87
test r9, r9
cmovz r11, r8
@@ -163,10 +205,25 @@ hex2str:
inc rcx
test rax, rax
jnz .convert
mov word [rsi], 'x0'
inc rsi
add rcx, 2
sub r10, rcx
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 r8
loop .paddingLoop
mov rcx, r8
.noPadding:
dec rsi
lea rdi, [rel cnvtBuff]
.makeString:
mov al, [rsi]
@@ -178,6 +235,7 @@ hex2str:
.quit:
lea rax, [rel cnvtBuff]
pop r12
ret
;----- bin2str(uint, padLen, bool padZeroes) -----;
@@ -223,14 +281,10 @@ bin2str:
cmp rsi, rcx
jl .noPadding
mov r8, rcx
push rsi
push rdx
mov rdi, rsi
xor rsi, rsi
mov rdx, 64
call clamp
pop rdx
pop rsi
mov rcx, rax
.paddingLoop:
mov byte [r9], r10b

View File

@@ -92,6 +92,16 @@ section .rodata
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
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()
msgStrlen db NL,"TEST strlen()",NL,EOS
@@ -350,6 +360,51 @@ _start:
mov rdx, 5
mov rcx, 5
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
;---