From ee17ec68e0e96607c82f2f3f00a63d1ae2e8fd94 Mon Sep 17 00:00:00 2001 From: Kwarde Date: Sat, 12 Jul 2025 07:48:21 +0200 Subject: [PATCH] printf(): Allow padding (spaces or zeroes) for %b --- src/PRINTF_PADDING_TEST.asm | 10 ------- src/console.asm | 45 +++++++++++++++++++++-------- src/convert.asm | 56 +++++++++++++++++++++++++++---------- src/tests.asm | 13 +++++++++ 4 files changed, 88 insertions(+), 36 deletions(-) delete mode 100644 src/PRINTF_PADDING_TEST.asm diff --git a/src/PRINTF_PADDING_TEST.asm b/src/PRINTF_PADDING_TEST.asm deleted file mode 100644 index b3d4f13..0000000 --- a/src/PRINTF_PADDING_TEST.asm +++ /dev/null @@ -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 diff --git a/src/console.asm b/src/console.asm index 3cf2b71..2af0883 100644 --- a/src/console.asm +++ b/src/console.asm @@ -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 diff --git a/src/convert.asm b/src/convert.asm index 97aaf3e..cbe8dcd 100644 --- a/src/convert.asm +++ b/src/convert.asm @@ -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 diff --git a/src/tests.asm b/src/tests.asm index fcf6502..4a260ea 100644 --- a/src/tests.asm +++ b/src/tests.asm @@ -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 ;---