From 8a18695328a7a9ee402375867ccc383320f87d71 Mon Sep 17 00:00:00 2001 From: Kwarde Date: Sat, 26 Jul 2025 00:50:09 +0200 Subject: [PATCH] __INTERNAL_fmt: Add description + return with errno -EBADF if FD is lower than FD_stdout (1) --- src/console.asm | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/console.asm b/src/console.asm index d623eb2..6b9f176 100644 --- a/src/console.asm +++ b/src/console.asm @@ -101,6 +101,16 @@ printf: mov rax, FD_stdout jmp __INTERNAL_fmt +;----- __INTERNAL_fmt(*format[], ...) -----; +; See printf description above, + +; 1) Return value can be amount of printed characters or -errno (eg if bad FD was passed, -EBADF is returned) +; 2) FD has to be passed via RAX (this is clearly an INTERNAL function so passed arguments are slightly different, that is, RAX required for FD) +; 3) FOR DEVS: When writing an I/O function that calls this wrapper, make sure that: +; - That function has function prologue (ie push rbp + mov rbp, rsp) +; - __INTERNAL_fmt is called via CALL and not a simple JMP like in printf +; This is because in such I/O functions, first argument should be file descriptor, and following SYS V ABI, that first argument is passed to RDI +; However since __INTERNAL_fmt expects FD via RAX, all arguments have to be shifted. Due to this, argument in R9 becomes a stack argument +; Because of that, __INTERNAL_fmt has to load from stack with a different offset; +24 bytes extra (extra +8 for function call, extra +8 for function prologue and extra +8 to account for possible R9 arg becoming a stack arg) __INTERNAL_fmt: %macro load_arg 1 cmp r14, 4 @@ -162,6 +172,11 @@ __INTERNAL_fmt: %endmacro ; entry: + cmp rax, 0 + jg .start_fmt + mov rax, -EBADF + ret + .start_fmt: push rbp mov rbp, rsp push r12