diff --git a/src/console.asm b/src/console.asm index 403577f..6f64a4a 100644 --- a/src/console.asm +++ b/src/console.asm @@ -123,6 +123,9 @@ eprintf: ; 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) +; +; To make it even more complicated, instead of simply writing to a buffer and simply printing to given FD, it is now also possible to write to memory (array) directly (used for format) +; To achieve that, pass ~RAX (thus ~pointer_to_array) and push length of array to the stack (from within function wrapper). See format() __INTERNAL_fmt: %macro load_arg 1 cmp r14, 4 @@ -132,10 +135,18 @@ __INTERNAL_fmt: %%fromStack: cmp r15, FD_stderr jle %%stackNoShift - mov %1, [rbp + (RBP_OFFSET_CALLER*2 + SIZE_QWORD) + ((r14-5) * SIZE_QWORD)] + test rbx, rbx + jnz %%stackShift_format + mov %1, [rbp + (RBP_OFFSET_CALLER*2 + SIZE_QWORD) + ((r14-5) * SIZE_QWORD)] ;Offset when called from wrapper like fwrite() (shifted args, output is to FD) + jmp %%continue + %%stackShift_format: + mov %1, [rbp + (RBP_OFFSET_CALLER*2 + SIZE_QWORD*4) + ((r14-5) * SIZE_QWORD)] ;Offset when called from wrapper like format() (shifted args, output is memory; extra push (+stack offset) for length of array) + ;Not entirely sure why I need to do SIZE_QWORD*4 though, should be *3 (because of one push and one stack offset: 16 bytes) + ;At %%fromStack I was also not sure why (according to comment at description: '+8 to account for possible R9 arg becoming a stack arg'); this does not apply + ;It 1*8 is needed it checks out: 1 + 2 + that extra 1 = 4. Still not sure where the extra 8 is coming from. jmp %%continue %%stackNoShift: - mov %1, [rbp + RBP_OFFSET_CALLER + ((r14-5) * SIZE_QWORD)] + mov %1, [rbp + RBP_OFFSET_CALLER + ((r14-5) * SIZE_QWORD)] ;Offset when called from wrapper like printf (no shifted args) %%continue: %endmacro diff --git a/src/string.asm b/src/string.asm index 8787b2c..1e106f6 100644 --- a/src/string.asm +++ b/src/string.asm @@ -234,9 +234,9 @@ format: mov rbp, rsp mov rax, rdi - not rax ;__INTERNAL_fmt; ~FD => Mem + not rax ;__INTERNAL_fmt; ~RAX => to mem instead of fd sub rsp, SIZE_QWORD - push rsi ;__INTERNAL_fmt: pop len from stack if rax is signed + push rsi lea rdi, [rdx] mov rsi, rcx mov rdx, r8