Adds format(), modified __INTERNAL_fmt to allow writing to memory (instead of writing to given FD)

This commit is contained in:
2025-07-31 14:18:00 +02:00
parent c36ae377ba
commit 00568e2e7c
2 changed files with 112 additions and 29 deletions

View File

@@ -1,6 +1,7 @@
%include "src/constants.asm" %include "src/constants.asm"
extern strlen extern strlen
extern strcat
extern itoa extern itoa
extern utoa extern utoa
@@ -88,6 +89,7 @@ puts:
; \t Tab ; \t Tab
; Used registers: ; Used registers:
; rax* (ret) amount of printed characters ; rax* (ret) amount of printed characters
; rbx Length of array being written to (if rax != FD)
; rdi* (arg) pointer to format[] to format and print >> pointer to buffer ; rdi* (arg) pointer to format[] to format and print >> pointer to buffer
; rsi* (optional arg) >> Used for inserting strings to buffer ; rsi* (optional arg) >> Used for inserting strings to buffer
; rdx* (optional arg) >> misc ; rdx* (optional arg) >> misc
@@ -181,7 +183,32 @@ __INTERNAL_fmt:
jmp .insertString jmp .insertString
%endmacro %endmacro
%macro check_formatted_len 2 ;check_format_len [return_label] [offset]
test rbx, rbx
jz %%checkBufferLen
cmp r11, rbx
jae .wrapup
jmp .flushReturn_%1
%%checkBufferLen:
mov r9b, %1
cmp r10, __fmt_BuffLen-%2
je .flushBuffer
.flushReturn_%1:
%endmacro
%macro write_format_data 3 ;write_format_data [size] [offset] [what]
test rbx, rbx
jz %%writeToBuffer
mov %1 [r15 + %2], %3
jmp %%cnt
%%writeToBuffer:
mov %1 [__fmt_Buff + %2], %3
%%cnt:
%endmacro
; entry: ; entry:
test rax, rax
js .start_fmt ;jump if signed; FD => Mem
cmp rax, 0 cmp rax, 0
jg .start_fmt jg .start_fmt
mov rax, -EBADF mov rax, -EBADF
@@ -189,12 +216,20 @@ __INTERNAL_fmt:
.start_fmt: .start_fmt:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
sub rsp, SIZE_QWORD
push rbx
push r12 push r12
push r13 push r13
push r14 push r14
push r15 push r15
mov r15, rax mov r15, rax
xor rbx, rbx
test r15, r15
jns .checkEmptyStr
not r15
mov rbx, [rbp + RBP_OFFSET_CALLER]
.checkEmptyStr:
cmp byte [rdi], EOS cmp byte [rdi], EOS
je .emptyStr je .emptyStr
@@ -213,16 +248,13 @@ __INTERNAL_fmt:
.process: .process:
cmp byte [rdi], EOS cmp byte [rdi], EOS
je .wrapup je .wrapup
xor r9b, r9b check_formatted_len 0,1
cmp r10, __fmt_BuffLen-1
je .flushBuffer
.flushReturn_0:
cmp byte [rdi], '\' cmp byte [rdi], '\'
je .asciiReplacement je .asciiReplacement
cmp byte [rdi], '%' cmp byte [rdi], '%'
je .argReplacement je .argReplacement
mov r8b, [rdi] mov r8b, [rdi]
mov [__fmt_Buff+r10], r8b write_format_data byte,r10,r8b
inc r10 inc r10
inc r11 inc r11
inc rdi inc rdi
@@ -240,15 +272,10 @@ __INTERNAL_fmt:
cmp byte [rdi + 1], 't' cmp byte [rdi + 1], 't'
cmove r9, r8 cmove r9, r8
je .replaceAscii je .replaceAscii
jmp .invalidReplacement jmp .invalidReplacement
.replaceAscii: .replaceAscii:
mov r8b, r9b check_formatted_len 1, 1
mov r9b, 2 write_format_data byte,r10,r8b
cmp r10, __fmt_BuffLen-1
je .flushBuffer
.flushReturn_2:
mov [__fmt_Buff + r10], r8b
add rdi, 2 add rdi, 2
inc r10 inc r10
inc r11 inc r11
@@ -342,7 +369,7 @@ __INTERNAL_fmt:
cmp byte [rdi + 1], '\' cmp byte [rdi + 1], '\'
je .invalidReplacement_specialChar; '%\n' would become "'%','\','n'" instead of "'%',EOS" when inserting full invalid specifier. je .invalidReplacement_specialChar; '%\n' would become "'%','\','n'" instead of "'%',EOS" when inserting full invalid specifier.
mov r9w, word [rdi] mov r9w, word [rdi]
mov [__fmt_Buff+r10], r9w write_format_data word,r10,r9w
add rdi, 2 add rdi, 2
add r10, 2 add r10, 2
add r11, 2 add r11, 2
@@ -350,7 +377,7 @@ __INTERNAL_fmt:
jmp .process jmp .process
.invalidReplacement_specialChar: .invalidReplacement_specialChar:
mov r9b, byte [rdi] mov r9b, byte [rdi]
mov [__fmt_Buff+r10], r9b write_format_data byte,r10,r9b
inc rdi inc rdi
inc r10 inc r10
inc r11 inc r11
@@ -405,14 +432,10 @@ __INTERNAL_fmt:
.insertString: .insertString:
test rsi, rsi test rsi, rsi
jnz .doInsertString jnz .doInsertString
;rsi = NULL: check_formatted_len 2, 7
mov r9b, 3 write_format_data byte,r10,'('
cmp r10, __fmt_BuffLen-7 write_format_data qword,r10+1,'null'
je .flushBuffer write_format_data byte,r10+5,')'
.flushReturn_3:
mov byte [__fmt_Buff + r10], '('
mov qword [__fmt_Buff + r10 + 1], 'null'
mov byte [__fmt_Buff + r10 + 5], ')'
add r10, 6 add r10, 6
add r11, 6 add r11, 6
jmp .endInsertString jmp .endInsertString
@@ -420,12 +443,9 @@ __INTERNAL_fmt:
.doInsertString: .doInsertString:
cmp byte [rsi], EOS cmp byte [rsi], EOS
je .endInsertString je .endInsertString
mov r9b, 1 check_formatted_len 3, 1
cmp r10, __fmt_BuffLen-1
je .flushBuffer
.flushReturn_1:
mov r8b, byte [rsi] mov r8b, byte [rsi]
mov [__fmt_Buff + r10], r8b write_format_data byte,r10,r8b
inc rsi inc rsi
inc r10 inc r10
inc r11 inc r11
@@ -438,7 +458,7 @@ __INTERNAL_fmt:
;--- Insert char to buffer ---; ;--- Insert char to buffer ---;
.insertChar: .insertChar:
mov [__fmt_Buff + r10], sil write_format_data byte,r10,sil
add rdi, 2 add rdi, 2
add r10, 1 add r10, 1
add r11, 1 add r11, 1
@@ -447,6 +467,22 @@ __INTERNAL_fmt:
jmp .process jmp .process
.flushBuffer: .flushBuffer:
test rbx, rbx
jz .flush_print
sub rsp, SIZE_QWORD
push rdi
push rsi
push rdx
lea rdi, [r15]
lea rsi, [rel __fmt_Buff]
mov rdx, rbx
call strcat
pop rdx
pop rsi
pop rdi
add rsp, SIZE_QWORD
jmp .flush_ret
.flush_print:
push rdi push rdi
push rsi push rsi
push rdx push rdx
@@ -463,7 +499,7 @@ __INTERNAL_fmt:
test rax, rax test rax, rax
js .quit js .quit
xor r10, r10 xor r10, r10
.flush_ret:
cmp r9b, 0 cmp r9b, 0
je .flushReturn_0 je .flushReturn_0
cmp r9b, 1 cmp r9b, 1
@@ -474,6 +510,19 @@ __INTERNAL_fmt:
je .flushReturn_3 je .flushReturn_3
.wrapup: .wrapup:
test rbx, rbx
jz .wrapup_print
mov byte [r15+r10+1], EOS
lea rdi, [r15]
lea rsi, [rel __fmt_Buff]
mov rdx, rbx
sub rsp, SIZE_QWORD
push r11
call strcat
pop rax
add rsp, SIZE_QWORD
jmp .quit
.wrapup_print:
mov rax, NR_write mov rax, NR_write
mov rdi, r15 mov rdi, r15
lea rsi, [rel __fmt_Buff] lea rsi, [rel __fmt_Buff]
@@ -493,6 +542,8 @@ __INTERNAL_fmt:
pop r14 pop r14
pop r13 pop r13
pop r12 pop r12
pop rbx
add rsp, SIZE_QWORD
leave leave
ret ret

View File

@@ -1,5 +1,7 @@
%include "src/constants.asm" %include "src/constants.asm"
extern __INTERNAL_fmt
section .text section .text
global strlen global strlen
global strcpy global strcpy
@@ -7,6 +9,7 @@ section .text
global strclr global strclr
global strcmp global strcmp
global strfind global strfind
global format
;----- strlen(*str[]) -----; ;----- strlen(*str[]) -----;
; Gets the length of given string ; Gets the length of given string
@@ -216,3 +219,32 @@ strfind:
mov rax, r8 mov rax, r8
.quit: .quit:
ret ret
;----- format(*dest[], len, *fmt[], ...) -----;
; Formats a string and writes it to memory.
; See __INTERNAL_fmt for valid specifiers
; Return value: Amount of characters written to dest[]
; Used registers:
; rax* (ret)
; rdi* (arg) Pointer to dest[]
; rsi* (arg) Size of dest[]
; rdx* (arg) Pointer to fmt[]
format:
push rbp
mov rbp, rsp
mov rax, rdi
not rax ;__INTERNAL_fmt; ~FD => Mem
sub rsp, SIZE_QWORD
push rsi ;__INTERNAL_fmt: pop len from stack if rax is signed
lea rdi, [rdx]
mov rsi, rcx
mov rdx, r8
mov rcx, r9
mov r8, [rbp + RBP_OFFSET_CALLER + SIZE_QWORD * 0]
mov r9, [rbp + RBP_OFFSET_CALLER + SIZE_QWORD * 1]
call __INTERNAL_fmt
add rsp, SIZE_QWORD * 2
leave
ret