diff --git a/.gitignore b/.gitignore index a543960..445187e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.lst *.o +*.txt tests diff --git a/console.asm b/console.asm index 350e1bf..2d82cec 100644 --- a/console.asm +++ b/console.asm @@ -1,3 +1,4 @@ +extern NR_write extern strlen section .rodata @@ -14,7 +15,7 @@ print: call strlen mov rdx, rax - mov rax, 1 + mov rax, NR_write mov rsi, rdi mov rdi, 1 syscall @@ -30,7 +31,7 @@ puts: mov r10, rdi call print mov rdi, r10 - mov rax, 1 + mov rax, NR_write mov rdi, 1 mov rsi, NL mov rdx, 1 diff --git a/constants.asm b/constants.asm index 334b36f..ddf2662 100644 --- a/constants.asm +++ b/constants.asm @@ -1,6 +1,18 @@ section .rodata + global NR_read + global NR_write + global NR_open + global NR_close + global EOS global NL - EOS equ 0x0 - NL equ 0xA + ;syscalls + NR_read equ 0 + NR_write equ 1 + NR_open equ 2 + NR_close equ 3 + + ;ascii + EOS equ 0x0 + NL equ 0xA diff --git a/file.asm b/file.asm new file mode 100644 index 0000000..bfeb0a6 --- /dev/null +++ b/file.asm @@ -0,0 +1,110 @@ +extern NR_read +extern NR_write +extern NR_open +extern NR_close + +extern strlen + +section .rodata + O_RDONLY equ 00000000q + O_WRONLY equ 00000001q + O_RDWR equ 00000002q + O_CREAT equ 00000100q + O_TRUNC equ 00001000q + O_APPEND equ 00002000q + +section .text + global fopen + global fclose + global fwrite + +;----- fopen(const char *filename, const char *mode) -----; +; return value: pointer to file or NULL if file failed to open +; ┌─────────────┬───────────────────────────────┐ +; │fopen() mode │ open() flags │ +; ├─────────────┼───────────────────────────────┤ +; │ r │ O_RDONLY │ +; ├─────────────┼───────────────────────────────┤ +; │ w │ O_WRONLY | O_CREAT | O_TRUNC │ +; ├─────────────┼───────────────────────────────┤ +; │ a │ O_WRONLY | O_CREAT | O_APPEND │ +; ├─────────────┼───────────────────────────────┤ +; │ R │ O_RDWR │ +; ├─────────────┼───────────────────────────────┤ +; │ W │ O_RDWR | O_CREAT | O_TRUNC │ +; ├─────────────┼───────────────────────────────┤ +; │ A │ O_RDWR | O_CREAT | O_APPEND │ +; └─────────────┴───────────────────────────────┘ +fopen: + push rbp + mov rbp, rsp + + cmp byte [rsi], 'r' + je .setMode_r + cmp byte [rsi], 'w' + je .setMode_w + cmp byte [rsi], 'a' + je .setMode_a + cmp byte [rsi], 'R' + je .setMode_R + cmp byte [rsi], 'W' + je .setMode_W + cmp byte [rsi], 'A' + je .setMode_A + xor rax, rax + jmp .quit + + .setMode_r: + mov rsi, O_RDONLY + jmp .open + .setMode_w: + mov rsi, O_WRONLY | O_CREAT | O_TRUNC + jmp .open + .setMode_a: + mov rsi, O_WRONLY | O_CREAT | O_APPEND + jmp .open + .setMode_R: + mov rsi, O_RDWR + jmp .open + .setMode_W: + mov rsi, O_RDWR | O_CREAT | O_TRUNC + jmp .open + .setMode_A: + mov rsi, O_RDWR | O_CREAT | O_APPEND + jmp .open + + .open: + mov rax, NR_open + syscall + + .quit: + leave + ret +;----- fclose(FILE* fp) -----; +; return value: 0 on success, below 0 otherwise +fclose: + push rbp + mov rbp, rsp + + mov rax, NR_close + syscall + + leave + ret +;----- fwrite(FILE* fp, char* str) -----; +; writes a string to opened file +; return value: 0 on success, below 0 otherwise +fwrite: + push rbp + mov rbp, rsp + + mov r9, rdi + mov rdi, rsi + call strlen + mov rdx, rax + mov rax, NR_write + mov rdi, r9 + syscall + + leave + ret diff --git a/makefile b/makefile index 134be9f..4f03c41 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ -tests: tests.o constants.o core.o console.o string.o - gcc tests.o constants.o core.o console.o string.o -o tests -no-pie -z noexecstack +tests: tests.o constants.o core.o console.o string.o file.o + gcc tests.o constants.o core.o console.o string.o file.o -o tests -no-pie -z noexecstack tests.o: tests.asm nasm tests.asm -f elf64 -l tests.lst -g -F dwarf constants.o: constants.asm @@ -10,6 +10,8 @@ console.o: console.asm nasm console.asm -f elf64 -l console.lst -g -F dwarf string.o: string.asm nasm string.asm -f elf64 -l string.lst -g -F dwarf +file.o: file.asm + nasm file.asm -f elf64 -l file.lst -g -F dwarf clean: - rm -f tests *.lst *.o + rm -f tests *.lst *.o testFile1.txt diff --git a/string.asm b/string.asm index decfd05..ce9a518 100644 --- a/string.asm +++ b/string.asm @@ -44,8 +44,8 @@ strcpy: .0f: mov byte [r11], 0x0 - cmp rcx, 0 - je .quit + test rcx, rcx + jz .quit mov rax, rdi .quit: diff --git a/tests.asm b/tests.asm index f4c3778..41ae523 100644 --- a/tests.asm +++ b/tests.asm @@ -23,6 +23,10 @@ extern strclr extern strlclr extern strcat extern strcmp +;file.asm +extern fopen +extern fclose +extern fwrite section .rodata PRINT_nums equ 1 @@ -42,6 +46,7 @@ section .rodata TEST_tolower equ 1 TEST_toupper equ 1 TEST_strcmp equ 1 + TEST_file1 equ 1 num1 dq 69 num2 dq 0xFFFFFF @@ -141,6 +146,16 @@ section .rodata msgStrcmp4 db "TEST strcmp(str4, str1): %d",NL,EOS msgStrcmp5 db "TEST strcmp(str1, str4): %d",NL,EOS msgStrcmp6 db "TEST strcmp(str1, str1): %d",NL,EOS + ; fopen(), fwrite(), fclose() + testFile1 db "testFile1.txt",EOS + fileStr1 db "Hello file world!",EOS + fileMode_w db "w",EOS + msgFileB db NL,"# fopen(), fwrite(), fclose()",EOS + msgFileB1 db "TEST fopen('testFile1.txt', 'w'): %d",NL,EOS + msgFileB2 db "TEST fwrite(filePointer1, fileStr1): %d",NL,EOS + msgFileB3 db "TEST fclose(filePointer1): %d",NL,EOS +section .data + filePointer1 dq 0 section .bss strBuff1 resb 32 strBuff2 resb 8 @@ -712,6 +727,37 @@ main: lea rdi, [rel msgStrcmp6] call printf %ENDIF +%IF TEST_file1 + lea rdi, [rel msgFileB] + call puts + + ; TEST: fopen() + lea rdi, [rel testFile1] + lea rsi, [rel fileMode_w] + call fopen + mov r15, rax ;store filepointer to R15 + mov rsi, rax + xor rax, rax + lea rdi, [rel msgFileB1] + call printf + + ; TEST: fwrite() + mov rdi, r15 + lea rsi, [fileStr1] + call fwrite + mov rsi, rax + xor rax, rax + lea rdi, [rel msgFileB2] + call printf + + ; TEST: fclose() + mov rdi, r15 + call fclose + mov rsi, rax + xor rax, rax + lea rdi, [rel msgFileB3] + call printf +%ENDIF leave ret