printf->__INTERNAL_fmt. FD passed via RAX. fwrite now allows specifiers and variable arguments.
This commit is contained in:
@@ -11,6 +11,8 @@ section .bss
|
|||||||
printfBuff resb printfBuffLen
|
printfBuff resb printfBuffLen
|
||||||
printfArgs resq 5 ;5=>rsi,rdx,rcx,r8,r9
|
printfArgs resq 5 ;5=>rsi,rdx,rcx,r8,r9
|
||||||
section .text
|
section .text
|
||||||
|
global __INTERNAL_fmt
|
||||||
|
|
||||||
global print
|
global print
|
||||||
global puts
|
global puts
|
||||||
global printf
|
global printf
|
||||||
@@ -94,13 +96,23 @@ puts:
|
|||||||
; r12 Padding length
|
; r12 Padding length
|
||||||
; r13 Bitmask, 1 = insert specifier yes/no, 2 = use zeroes for padding yes/no
|
; r13 Bitmask, 1 = insert specifier yes/no, 2 = use zeroes for padding yes/no
|
||||||
; r14 Keeps track of amount of processed format specifiers
|
; r14 Keeps track of amount of processed format specifiers
|
||||||
|
; r15 Stores fd to write output to (passed to __INTERNAL_fmt via RAX)
|
||||||
printf:
|
printf:
|
||||||
|
mov rax, FD_stdout
|
||||||
|
jmp __INTERNAL_fmt
|
||||||
|
|
||||||
|
__INTERNAL_fmt:
|
||||||
%macro load_arg 1
|
%macro load_arg 1
|
||||||
cmp r14, 4
|
cmp r14, 4
|
||||||
ja %%fromStack
|
ja %%fromStack
|
||||||
mov %1, [printfArgs + SIZE_QWORD * r14]
|
mov %1, [printfArgs + SIZE_QWORD * r14]
|
||||||
jmp %%continue
|
jmp %%continue
|
||||||
%%fromStack:
|
%%fromStack:
|
||||||
|
cmp r15, FD_stdout
|
||||||
|
je %%stackNoShift
|
||||||
|
mov %1, [rbp + (RBP_OFFSET_CALLER*2 + SIZE_QWORD) + ((r14-5) * SIZE_QWORD)] ;non-printf functions calling __INTERNAL_fmt require RDI to be FD, all args shifted and rbp+RBP_OFFSET_CALLER to r9. Also requires function prologue and a CALL to __INTERNAL_fmt (not a JMP like in printf); hence the RBP_OFFSET_CALLER*2
|
||||||
|
jmp %%continue
|
||||||
|
%%stackNoShift:
|
||||||
mov %1, [rbp + RBP_OFFSET_CALLER + ((r14-5) * SIZE_QWORD)]
|
mov %1, [rbp + RBP_OFFSET_CALLER + ((r14-5) * SIZE_QWORD)]
|
||||||
%%continue:
|
%%continue:
|
||||||
%endmacro
|
%endmacro
|
||||||
@@ -152,10 +164,11 @@ printf:
|
|||||||
; entry:
|
; entry:
|
||||||
push rbp
|
push rbp
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
sub rsp, SIZE_QWORD
|
|
||||||
push r12
|
push r12
|
||||||
push r13
|
push r13
|
||||||
push r14
|
push r14
|
||||||
|
push r15
|
||||||
|
mov r15, rax
|
||||||
|
|
||||||
cmp byte [rdi], EOS
|
cmp byte [rdi], EOS
|
||||||
je .emptyStr
|
je .emptyStr
|
||||||
@@ -414,7 +427,7 @@ printf:
|
|||||||
push rdx
|
push rdx
|
||||||
push r11
|
push r11
|
||||||
mov rax, NR_write
|
mov rax, NR_write
|
||||||
mov rdi, FD_stdout
|
mov rdi, r15
|
||||||
lea rsi, [rel printfBuff]
|
lea rsi, [rel printfBuff]
|
||||||
mov rdx, r10
|
mov rdx, r10
|
||||||
syscall
|
syscall
|
||||||
@@ -435,7 +448,7 @@ printf:
|
|||||||
|
|
||||||
.wrapup:
|
.wrapup:
|
||||||
mov rax, NR_write
|
mov rax, NR_write
|
||||||
mov rdi, FD_stdout
|
mov rdi, r15
|
||||||
lea rsi, [rel printfBuff]
|
lea rsi, [rel printfBuff]
|
||||||
mov rdx, r10
|
mov rdx, r10
|
||||||
mov r10, r11
|
mov r10, r11
|
||||||
@@ -447,9 +460,9 @@ printf:
|
|||||||
xor rax, rax
|
xor rax, rax
|
||||||
|
|
||||||
.quit:
|
.quit:
|
||||||
|
pop r15
|
||||||
pop r14
|
pop r14
|
||||||
pop r13
|
pop r13
|
||||||
pop r12
|
pop r12
|
||||||
add rsp, SIZE_QWORD
|
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
51
src/file.asm
51
src/file.asm
@@ -1,5 +1,7 @@
|
|||||||
%include "src/constants.asm"
|
%include "src/constants.asm"
|
||||||
|
|
||||||
|
extern __INTERNAL_fmt
|
||||||
|
|
||||||
extern strlen
|
extern strlen
|
||||||
extern umask_get
|
extern umask_get
|
||||||
|
|
||||||
@@ -76,7 +78,7 @@ fopen:
|
|||||||
call fexist
|
call fexist
|
||||||
pop rsi
|
pop rsi
|
||||||
pop rdi
|
pop rdi
|
||||||
mov rax, 1
|
test rax, 1
|
||||||
jz %%createFile
|
jz %%createFile
|
||||||
jmp %1
|
jmp %1
|
||||||
%%createFile:
|
%%createFile:
|
||||||
@@ -86,7 +88,7 @@ fopen:
|
|||||||
pop rdi
|
pop rdi
|
||||||
push rdi
|
push rdi
|
||||||
not rax
|
not rax
|
||||||
mov rsi, 00666q
|
mov rsi, 0666q
|
||||||
and rsi, rax
|
and rsi, rax
|
||||||
mov rax, NR_creat
|
mov rax, NR_creat
|
||||||
syscall
|
syscall
|
||||||
@@ -155,6 +157,7 @@ fopen:
|
|||||||
; rax* (ret)
|
; rax* (ret)
|
||||||
; rdi (arg) Pointer to opened file
|
; rdi (arg) Pointer to opened file
|
||||||
fclose:
|
fclose:
|
||||||
|
sub rsp, SIZE_QWORD
|
||||||
cmp rdi, 3
|
cmp rdi, 3
|
||||||
jl .invalid_fd ;disallow closing stdin,stdout,stderr
|
jl .invalid_fd ;disallow closing stdin,stdout,stderr
|
||||||
mov rax, NR_close
|
mov rax, NR_close
|
||||||
@@ -165,6 +168,7 @@ fclose:
|
|||||||
mov rax, -EINVAL
|
mov rax, -EINVAL
|
||||||
|
|
||||||
.quit:
|
.quit:
|
||||||
|
add rsp, SIZE_QWORD
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;----- fexist(*file[]) -----;
|
;----- fexist(*file[]) -----;
|
||||||
@@ -174,7 +178,7 @@ fclose:
|
|||||||
; rax* (ret)
|
; rax* (ret)
|
||||||
; rdi (arg) Pointer to string holding (path+)file name
|
; rdi (arg) Pointer to string holding (path+)file name
|
||||||
fexist:
|
fexist:
|
||||||
;sub rsp, SIZE_QWORD
|
sub rsp, SIZE_QWORD
|
||||||
mov rsi, 'r'
|
mov rsi, 'r'
|
||||||
call fopen
|
call fopen
|
||||||
test rax, rax
|
test rax, rax
|
||||||
@@ -186,35 +190,32 @@ fexist:
|
|||||||
.not_exist:
|
.not_exist:
|
||||||
xor rax, rax
|
xor rax, rax
|
||||||
.quit:
|
.quit:
|
||||||
;add rsp, SIZE_QWORD
|
add rsp, SIZE_QWORD
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;--- fwrite(*filePointer, *data[]) -----;
|
;--- fwrite(*filePointer, *data[], ...) -----;
|
||||||
; Writes data to given file
|
; Writes data to given file. Allows format specifiers and variable arguments (see `__INTERNAL_fmt` for supported specifiers)
|
||||||
; Return value: Length of given string(data[]), 0 if nothing was written (eg invalid file or file not writable, or data[] is empty)
|
; Return value: Length of given string(data[]), 0 if nothing was written (eg invalid file or file not writable, or data[] is empty)
|
||||||
; Used registers:
|
; Used registers:
|
||||||
; rax* (ret)
|
; rax* (ret)
|
||||||
; rdi (arg) Pointer to file
|
; rdi (arg) Pointer to file
|
||||||
; rsi (arg) Data to write
|
; rsi (arg) Data to write
|
||||||
; r8* Backs up rdi
|
|
||||||
; r9* Backs up rsi
|
|
||||||
fwrite:
|
fwrite:
|
||||||
sub rsp, SIZE_QWORD
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
cmp rdi, 2
|
||||||
|
jg .cnt
|
||||||
xor rax, rax
|
xor rax, rax
|
||||||
cmp rdi, 3
|
leave
|
||||||
jl .quit
|
ret
|
||||||
mov r8, rdi
|
.cnt:
|
||||||
mov r9, rsi
|
mov rax, rdi
|
||||||
|
mov rdi, rsi
|
||||||
mov rdi, rsi
|
mov rsi, rdx
|
||||||
call strlen
|
mov rdx, rcx
|
||||||
|
mov rcx, r8
|
||||||
mov rdx, rax
|
mov r8, r9
|
||||||
mov rax, NR_write
|
mov r9, [rbp + RBP_OFFSET_CALLER]
|
||||||
mov rdi, r8
|
call __INTERNAL_fmt
|
||||||
mov rsi, r9
|
leave
|
||||||
syscall
|
|
||||||
|
|
||||||
.quit:
|
|
||||||
add rsp, SIZE_QWORD
|
|
||||||
ret
|
ret
|
||||||
|
@@ -330,6 +330,8 @@ section .rodata
|
|||||||
addTest(fwrite1, "fwrite(fp1, 'Hello world!\n') //mode 'a'")
|
addTest(fwrite1, "fwrite(fp1, 'Hello world!\n') //mode 'a'")
|
||||||
addTest(fwrite2, "fwrite(fp1, 'How are you doing?\n') //mode 'a'")
|
addTest(fwrite2, "fwrite(fp1, 'How are you doing?\n') //mode 'a'")
|
||||||
addTest(fwrite3, "fwrite(fp1, 'Howdy environment!') //mode 'w'")
|
addTest(fwrite3, "fwrite(fp1, 'Howdy environment!') //mode 'w'")
|
||||||
|
addTest(fwrite4, "fwrite(fp1, ''%c%c%c%c%c%c%c%c\n'', 'H', 'e', 'l', 'l', 'o', '!', '?', '!')")
|
||||||
|
fwriteStr1 db "%c%c%c%c%c%c%c%c\n",EOS
|
||||||
|
|
||||||
section .bss
|
section .bss
|
||||||
strBuff1 resb 64
|
strBuff1 resb 64
|
||||||
@@ -1198,6 +1200,29 @@ _start:
|
|||||||
call fwrite
|
call fwrite
|
||||||
assert_eq(18)
|
assert_eq(18)
|
||||||
|
|
||||||
|
; Re-open in write mode, again
|
||||||
|
mov rdi, [fp1]
|
||||||
|
call fclose
|
||||||
|
lea rdi, [rel file1]
|
||||||
|
mov rsi, 'w'
|
||||||
|
call fopen
|
||||||
|
mov [fp1], rax
|
||||||
|
|
||||||
|
; TEST 4
|
||||||
|
printTest(fwrite4)
|
||||||
|
mov rdi, [fp1]
|
||||||
|
lea rsi, [fwriteStr1]
|
||||||
|
mov rdx, 'H'
|
||||||
|
mov rcx, 'e'
|
||||||
|
mov r8, 'l'
|
||||||
|
mov r9, 'l'
|
||||||
|
push byte '!'
|
||||||
|
push byte '?'
|
||||||
|
push byte '!'
|
||||||
|
push byte 'o'
|
||||||
|
call fwrite
|
||||||
|
add rsp, SIZE_QWORD * 4
|
||||||
|
|
||||||
; Close file1
|
; Close file1
|
||||||
mov rdi, [fp1]
|
mov rdi, [fp1]
|
||||||
call fclose
|
call fclose
|
||||||
|
Reference in New Issue
Block a user