printf(): Add support for %s, fix buffer flushing (length given was r11, not r10)

This commit is contained in:
2025-07-06 20:50:07 +02:00
parent cc214ed5e5
commit 3ccad56d76
2 changed files with 70 additions and 20 deletions

View File

@@ -7,7 +7,7 @@ section .rodata
printfBuffLen equ 128
section .bss
printfBuff resb printfBuffLen
printfArgs resq 5
printfArgs resq 5 ;5=>rsi,rdx,rcx,r8,r9
section .text
global print
global puts
@@ -59,15 +59,17 @@ puts:
; Return value: Amount of printed characters
; Supported specifiers:
; %% Literal percentage sign
; %s String
; <!> 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:
; rax (ret) amount of printed characters
; rdi (arg) pointer to format[] to format and print
; rsi (optional arg)
; rdx (optional arg) >> Keeps track of amount of processed format specifiers
; rax* (ret) amount of printed characters
; rdi* (arg) pointer to format[] to format and print
; rsi* (optional arg) >> Used for inserting strings to buffer
; rdx* (optional arg) >> Keeps track of amount of processed format specifiers
; rcx (optional arg)
; r8 (optional arg) >> Used for moving characters
; r9 (optional arg) >> Keeps track of where to jump after flushing buffer
; r8* (optional arg) >> Used for moving characters
; r9* (optional arg) >> Keeps track of where to jump after flushing buffer
; r10* Keeps track of current index of printfBuff
; r11* Keeps track of total characters (return value)
printf:
@@ -77,16 +79,17 @@ printf:
cmp byte [rdi], EOS
je .emptyStr
xor r10, r10
xor r11, r11
; Store arguments to memory - easier to load data + more available registers (= less stack usage)
mov [printfArgs + SIZE_QWORD * 0], rsi
mov [printfArgs + SIZE_QWORD * 1], rdx
mov [printfArgs + SIZE_QWORD * 2], rcx
mov [printfArgs + SIZE_QWORD * 3], r8
mov [printfArgs + SIZE_QWORD * 4], r9
mov [rel printfArgs + SIZE_QWORD * 0], rsi
mov [rel printfArgs + SIZE_QWORD * 1], rdx
mov [rel printfArgs + SIZE_QWORD * 2], rcx
mov [rel printfArgs + SIZE_QWORD * 3], r8
mov [rel printfArgs + SIZE_QWORD * 4], r9
xor rdx, rdx
xor r10, r10
xor r11, r11
.process:
cmp byte [rdi], EOS
@@ -109,6 +112,8 @@ printf:
je .wrapup
cmp byte [rdi + 1], '%'
je .rep_pct
cmp byte [rdi + 1], 's'
je .rep_s
;--- Invalid ---;
mov r9w, word [rdi]
@@ -125,22 +130,55 @@ printf:
add r10, 1
add r11, 1
jmp .process
;--- '%s' ---;
.rep_s:
cmp rdx, 4
ja .s_fromStack
mov rsi, [printfArgs + SIZE_QWORD * rdx]
jmp .insertString
.s_fromStack:
lea rsi, [rbp + RBP_OFFSET_CALLER + ((rdx-5) * SIZE_QWORD)]
;--- Insert string to buffer ---;
.insertString:
cmp byte [rsi], EOS
je .endInsertString
mov r9b, 1
cmp r10, printfBuffLen-1
je .flushBuffer
.flushReturn_1:
mov r8b, byte [rsi]
mov [printfBuff + r10], r8b
inc rsi
inc r10
inc r11
jmp .insertString
.endInsertString:
inc rdx
add rdi, 2
jmp .process
.flushBuffer:
push rdi
push rsi
push rdx
push r11
mov rax, NR_write
mov rdi, FD_stdout
lea rsi, [rel printfBuff]
mov rdx, r11
mov rdx, r10
syscall
pop r10
pop r11
pop rdx
pop rsi
pop rdi
xor r10, r10
cmp r9b, 0
je .flushReturn_0
cmp r9b, 1
je .flushReturn_1
.wrapup:
mov rax, NR_write

View File

@@ -34,8 +34,12 @@ section .rodata
; printf()
msgPrintf db "TEST printf()",NL,EOS
printf1 db TAB,"printf(",DQUO,"He%ll%o there%%%%%!%s%!%\n",DQUO,"): ",NL,TAB,TAB,EOS
printf1Str db "He%ll%o there%%%%%!%s%!%",NL,EOS
printf1 db TAB,"printf(",DQUO,"He%ll%o there%%%%%!%!%\n",DQUO,"): ",NL,TAB,TAB,EOS
printf1Str db "He%ll%o there%%%%%!%!%",NL,EOS
printf2 db TAB,"printf(",DQUO,"Are %s doing %s?\n",DQUO,", printf2Str1, printf2Str2): ",NL,TAB,TAB,EOS
printf2Str db "Are %s doing %s?",NL,EOS
printf2Str1 db "you",EOS
printf2Str2 db "okay",EOS
; strlen()
strlenStr1 db "Hello",EOS
@@ -94,6 +98,14 @@ _start:
call print
lea rdi, [rel printf1Str]
call printf
; TEST 2
lea rdi, [rel printf2]
call print
lea rdi, [rel printf2Str]
lea rsi, [rel printf2Str1]
lea rdx, [rel printf2Str2]
call printf
%endif
;---