From cc214ed5e50ab0a6fdc37308bb932579d4a08990 Mon Sep 17 00:00:00 2001 From: Kwarde Date: Sun, 6 Jul 2025 20:09:21 +0200 Subject: [PATCH] Adds basic printf() (currently only support '%%') --- src/console.asm | 118 +++++++++++++++++++++++++++++++++++++++++++++++- src/tests.asm | 21 +++++++++ 2 files changed, 137 insertions(+), 2 deletions(-) diff --git a/src/console.asm b/src/console.asm index 438352d..b6c0aaa 100644 --- a/src/console.asm +++ b/src/console.asm @@ -3,10 +3,15 @@ extern strlen section .rodata - mNL db NL + mNL db NL + printfBuffLen equ 128 +section .bss + printfBuff resb printfBuffLen + printfArgs resq 5 section .text global print global puts + global printf ;----- print(*str[]) -----; ; Prints given string to the console to stdout @@ -31,7 +36,10 @@ print: ; Prints given string to the console to stdout and prints a new line ; Return value: Amount of printed characters ; Used registers: -; +; rax* syscall >> (ret) amount of printed characters +; rdi* (arg) Pointer to str[] >> syscall arg (fd) +; rsi* syscall arg (pointer to str[]) +; rdx* syscall arg (length of str[]+1) puts: sub rsp, SIZE_QWORD call print @@ -45,3 +53,109 @@ puts: inc rax add rsp, SIZE_QWORD ret + +;----- printf(*format[], ...) -----; +; Formats and prints given string to console to stdout +; Return value: Amount of printed characters +; Supported specifiers: +; %% Literal percentage sign +; Unsupported specifiers are printed as-is +; 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 +; rcx (optional arg) +; 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: + push rbp + mov rbp, rsp + sub rsp, SIZE_QWORD + + 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 + + .process: + cmp byte [rdi], EOS + je .wrapup + mov r9b, 0 + cmp r10, printfBuffLen-1 + je .flushBuffer + .flushReturn_0: + cmp byte [rdi], '%' + je .argReplacement + mov r8b, [rdi] + mov [printfBuff+r10], r8b + inc r10 + inc r11 + inc rdi + jmp .process + + .argReplacement: + cmp byte [rdi + 1], EOS + je .wrapup + cmp byte [rdi + 1], '%' + je .rep_pct + + ;--- Invalid ---; + mov r9w, word [rdi] + mov [printfBuff+r10], r9w + add rdi, 2 + add r10, 2 + add r11, 2 + jmp .process + + ;--- '%%' ---; + .rep_pct: + mov [printfBuff+r10], byte '%' + add rdi, 2 + add r10, 1 + add r11, 1 + jmp .process + + + .flushBuffer: + push rdx + push r11 + mov rax, NR_write + mov rdi, FD_stdout + lea rsi, [rel printfBuff] + mov rdx, r11 + syscall + pop r10 + pop rdx + xor r10, r10 + + cmp r9b, 0 + je .flushReturn_0 + + .wrapup: + mov rax, NR_write + mov rdi, FD_stdout + lea rsi, [rel printfBuff] + mov rdx, r10 + mov r10, r11 + syscall + mov rax, r10 + jmp .quit + + .emptyStr: + xor rax, rax + + .quit: + add rsp, SIZE_QWORD + leave + ret diff --git a/src/tests.asm b/src/tests.asm index 0758fb3..e13e17f 100644 --- a/src/tests.asm +++ b/src/tests.asm @@ -5,6 +5,7 @@ extern exit ; console.asm extern print extern puts +extern printf ; string.asm extern strlen extern strcpy @@ -14,6 +15,7 @@ extern strcat section .rodata TEST_print equ 1 TEST_puts equ 1 + TEST_printf equ 1 TEST_strlen equ 1 TEST_strcpy equ 1 TEST_strcat equ 1 @@ -30,6 +32,11 @@ section .rodata ; puts() msgPuts db "TEST puts()",EOS + ; 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 + ; strlen() strlenStr1 db "Hello",EOS strlenStr2 db "Hello, world!",NL,EOS @@ -75,6 +82,20 @@ _start: call puts %endif +;--- +;--- printf() +;--- +%if TEST_printf + lea rdi, [rel msgPrintf] + call printf + + ; TEST 1 + lea rdi, [rel printf1] + call print + lea rdi, [rel printf1Str] + call printf +%endif + ;--- ;--- strlen() ;---