printf(): Allow padding (spaces or zeroes) for %b

This commit is contained in:
2025-07-12 07:48:21 +02:00
parent 971b1cbb86
commit ee17ec68e0
4 changed files with 88 additions and 36 deletions

View File

@@ -1,10 +0,0 @@
%include "src/constants.asm"
extern printf
section .rodata
msg db "%133769666b",NL,EOS
section .text
global _start
_start:
lea rdi, [rel msg]
mov rsi, 6
call printf

View File

@@ -84,6 +84,7 @@ puts:
; r10* Keeps track of current index of printfBuff
; r11* Keeps track of total characters (return value)
; r12 Padding for numbers (0=nopadding, >0=padding w/ spaces, NOT >0=padding w/ zeroes)
; r13 Padding: zeroes (=1) or spaces (=0)
printf:
%macro load_arg 1
cmp rdx, 4
@@ -100,9 +101,13 @@ printf:
push rax
push rdx
push rdi
push r9
push r10
%endmacro
%macro pop_regs 0
pop r10
pop r9
pop rdi
pop rdx
pop rax
@@ -112,6 +117,8 @@ printf:
; entry:
push rbp
mov rbp, rsp
push r12
push r13
cmp byte [rdi], EOS
je .emptyStr
@@ -148,14 +155,16 @@ printf:
je .wrapup
cmp byte [rdi + 1], '%'
je .rep_pct
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cmp byte [rdi + 1], '1' ;zero padding later!
xor r13, r13
mov r12, 1
cmp byte [rdi + 1], '0'
jb .noPadding
cmove r13, r12
cmp byte [rdi + 1], '9'
jg .noPadding
inc rdi ;point to after '%'
xor rcx, rcx ;length of padding number (set to 0 first)
xor r12, r12
xor rcx, rcx
inc rdi
.findPaddingNumLen:
cmp byte [rdi], EOS
je .wrapup
@@ -167,11 +176,10 @@ printf:
inc rdi
jmp .findPaddingNumLen
.getPadding:
dec rdi ;dont break .noPadding below (for cmp rdi+1)
dec rdi
push rdi
push rax
xor rax, rax
xor r12, r12 ;total len
mov r9, 1
.getPaddingLoop:
xor rax, rax
@@ -186,10 +194,10 @@ printf:
mov r9, rax
loop .getPaddingLoop
pop rax
pop rdi ;r12 should now store padding length
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; OK so at this point, padding (spaces, zeroes not yet supported) length is calculated correctly and string is replaced correctly.
; Now what remains is to actually add the spaces (and zeroes, eventually)
pop rdi
test r13, r13
jz .noPadding
not r12
.noPadding:
cmp byte [rdi + 1], 'c'
je .rep_c
@@ -270,6 +278,20 @@ printf:
load_arg rsi
push_regs
mov rdi, rsi
;
mov rdx, 0
test r12, r12
jz .callB2S
test r12, r12
js .notB2S
jmp .callB2S
.notB2S:
not r12
mov rdx, 1
jmp .callB2S
;
.callB2S:
mov rsi, r12
call bin2str
mov rsi, rax
pop_regs
@@ -342,6 +364,7 @@ printf:
xor rax, rax
.quit:
pop r13
pop r12
leave
ret

View File

@@ -1,5 +1,7 @@
%include "src/constants.asm"
extern clamp
section .bss
cnvtBuff resb 67
cnvtBuffRev resb 67
@@ -178,24 +180,30 @@ hex2str:
lea rax, [rel cnvtBuff]
ret
;----- bin2str(uint) -----;
;----- 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* modulo as calculated by div >> character storage for cnvtBuff
; 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* Points to cnvtBuff for writing characters
; rsi* (arg) Padding length
; r8* Dividor for div
; r9* Points to cnvtBuff for writing characters
; r10* padZeroes arg (since rdx used by DIV)
bin2str:
lea rsi, [rel cnvtBuffRev]
mov r10, ' '
mov r9, '0'
test rdx, rdx
cmovnz r10, r9
lea r9, [rel cnvtBuffRev]
test rdi, rdi
jnz .notZero
lea rsi, [rel cnvtBuff]
mov word [rsi], '0b'
mov byte [rsi + 2], '0'
mov byte [rsi + 3], EOS
lea r9, [rel cnvtBuff]
mov word [r9], '0b'
mov byte [r9 + 2], '0'
mov byte [r9 + 3], EOS
jmp .quit
.notZero:
@@ -206,20 +214,38 @@ bin2str:
mov r8, 2
div r8
add rdx, '0'
mov [rsi], dl
inc rsi
mov [r9], dl
inc r9
inc rcx
test rax, rax
jnz .convert
mov word [rsi], 'b0'
add rcx, 2
inc rsi
sub rsi, rcx
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
inc r9
inc r8
loop .paddingLoop
mov rcx, r8
.noPadding:
dec r9
lea rdi, [rel cnvtBuff]
.makeStringLoop:
mov al, [rsi]
mov al, [r9]
mov [rdi], al
inc rdi
dec rsi
dec r9
loop .makeStringLoop
mov byte [rdi], EOS

View File

@@ -10,6 +10,8 @@ extern min
extern minu
extern max
extern maxu
extern clamp
extern clampu
; console.asm
extern print
extern puts
@@ -88,6 +90,8 @@ section .rodata
printf4Str db "%i|%d|%u , %i|%d|%u",NL,EOS
printf5 db TAB,"printf(",DQUO,"%x|%X , %x|%X\n",DQUO,", 0xabcdeffedcba, 0x069bc0e, 666, -1): ",NL,TAB,TAB,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
printf6Str db "%b | %8b | %08b",NL,EOS
; strlen()
msgStrlen db NL,"TEST strlen()",NL,EOS
@@ -337,6 +341,15 @@ _start:
mov rcx, 666
mov r8, -1
call printf
; TEST 6
lea rdi, [rel printf6]
call print
lea rdi, [rel printf6Str]
mov rsi, 5
mov rdx, 5
mov rcx, 5
call printf
%endif
;---