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

View File

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

View File

@@ -10,6 +10,8 @@ extern min
extern minu extern minu
extern max extern max
extern maxu extern maxu
extern clamp
extern clampu
; console.asm ; console.asm
extern print extern print
extern puts extern puts
@@ -88,6 +90,8 @@ section .rodata
printf4Str db "%i|%d|%u , %i|%d|%u",NL,EOS 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 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 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() ; strlen()
msgStrlen db NL,"TEST strlen()",NL,EOS msgStrlen db NL,"TEST strlen()",NL,EOS
@@ -337,6 +341,15 @@ _start:
mov rcx, 666 mov rcx, 666
mov r8, -1 mov r8, -1
call printf 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 %endif
;--- ;---