From cd34fb3b2e235febb27d300da7f9902cc70fc8aa Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Sat, 11 Nov 2017 23:33:58 +0000 Subject: [PATCH] Added read-string and slurp functions System calls using Linux 64-bit syscalls in system.asm. Wrapper code in core.asm --- nasm/core.asm | 51 ++++++++++++++++++++++ nasm/system.asm | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ nasm/types.asm | 6 ++- 3 files changed, 169 insertions(+), 1 deletion(-) diff --git a/nasm/core.asm b/nasm/core.asm index e776538d..38f1e020 100644 --- a/nasm/core.asm +++ b/nasm/core.asm @@ -30,6 +30,9 @@ section .data static core_prn_symbol, db "prn" static core_str_symbol, db "str" static core_println_symbol, db "println" + + static core_read_string_symbol, db "read-string" + static core_slurp_symbol, db "slurp" ;; Strings @@ -89,6 +92,9 @@ core_environment: core_env_native core_prn_symbol, core_prn core_env_native core_str_symbol, core_str core_env_native core_println_symbol, core_println + + core_env_native core_read_string_symbol, core_read_string + core_env_native core_slurp_symbol, core_slurp ; ----------------- ; Put the environment in RAX @@ -562,3 +568,48 @@ core_prn_functions: call alloc_cons mov [rax], BYTE maltype_nil ret + +;; Given a string, calls read_str to get an AST +core_read_string: + mov al, BYTE [rsi] + mov ah, al + and ah, content_mask + cmp ah, content_pointer + jne .no_string + + mov rsi, [rsi + Cons.car] + mov al, BYTE [rsi] + cmp al, maltype_string + jne .no_string + + call read_str + ret + +.no_string: + ; Didn't get a string input + call alloc_cons + mov [rax], BYTE maltype_nil + ret + + +;; Reads a file into a string +core_slurp: + mov al, BYTE [rsi] + mov ah, al + and ah, content_mask + cmp ah, content_pointer + jne .no_string + + mov rsi, [rsi + Cons.car] + mov al, BYTE [rsi] + cmp al, maltype_string + jne .no_string + + call read_file + ret + +.no_string: + ; Didn't get a string input + call alloc_cons + mov [rax], BYTE maltype_nil + ret diff --git a/nasm/system.asm b/nasm/system.asm index 6389b2a6..de4d793b 100644 --- a/nasm/system.asm +++ b/nasm/system.asm @@ -3,6 +3,11 @@ ;;; This file contains system-specific functions, ;;; which use calls to the operating system (Linux) +section .data + static error_open_file_string, db "Error opening file " + static error_read_file_string, db "Error reading file " + +section .text ;; ------------------------------------------- ;; Prints a raw string to stdout @@ -91,3 +96,111 @@ read_line: pop rax ; Restore pointer to string mov DWORD [rax + Array.length], ebx ; Set string length ret + +;; Reads a file into a string +;; +;; Input: RSI - File name string (char Array) +;; +;; Returns: string in RAX +;; +;; Pieces from https://stackoverflow.com/questions/20133698/how-to-read-from-and-write-to-files-using-nasm-for-x86-64bit +read_file: + + mov rdi, rsi ; Filename + + ; Need to add null terminator + mov eax, DWORD [rdi + Array.length] + cmp eax, (array_chunk_len * 8) + je .error_filename ; File name too long + + ; Insert a null terminator + add rax, rdi + mov [rax + Array.data], BYTE 0 + + ; Open the file + mov rax, 2 + add rdi, Array.data; filename in RDI + xor rsi, rsi ; O_RDONLY in RSI + syscall + + ; Check for error (return -1) + cmp eax, 0 + jl .error_open + + mov rdi, rax ; File handle in RDI + + ; Create a string + push rdi + call string_new ; In RAX + pop rdi + + mov r9, rax ; Current Array + push rax ; This is popped in .done +.loop: + ; Read next chunk + push r9 + + mov rsi, r9 + add rsi, Array.data ; address + + mov rax, 0 ; sys_read + ; file handle in RDI + mov rdx, (array_chunk_len * 8) ; count + syscall + + pop r9 + + ; Characters read in RAX + + cmp rax, 0 + jl .error_read + + cmp rax, (array_chunk_len * 8) + jg .error_read + + mov [r9 + Array.length], DWORD eax + + jl .done + + ; May still be more to read. + ; Allocate another + call string_new + mov [r9 + Array.next], rax + mov r9, rax + jmp .loop + +.done: + ; Close the file + mov rax, 3 + ;rdi = file handle + syscall + + pop rax + ret + +.error_filename: +.error_open: + ; File name in RDI + sub rdi, Array.data + + ; Make the error message + mov rsi, error_open_file_string + mov edx, error_open_file_string.len + call raw_to_string + mov rsi, rax + mov cl, 39 ; (') + call string_append_char + mov rdx, rdi ; file name + call string_append_string + mov cl, 39 + call string_append_char + + ; Error message in RSI + jmp error_throw + +.error_read: + mov rsi, error_read_file_string + mov edx, error_read_file_string.len + call raw_to_string + mov rsi, rax + jmp error_throw diff --git a/nasm/types.asm b/nasm/types.asm index 3e9fed8c..7de8cf6a 100644 --- a/nasm/types.asm +++ b/nasm/types.asm @@ -387,8 +387,12 @@ incref_object: ;; ------------------------------------------- ;; String type - +;; ;; Create a new string, address in RAX +;; +;; Modifies registers +;; RBX +;; string_new: call alloc_array mov [rax], BYTE maltype_string