commit 26c2bec61a38027f700000e693d7578b9a3a3590 Author: victor Date: Mon Apr 28 17:20:24 2025 +0200 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e9dec8e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +vgcore* +debug +obj +*.o diff --git a/.project.gf b/.project.gf new file mode 100644 index 0000000..0982c60 --- /dev/null +++ b/.project.gf @@ -0,0 +1,4 @@ +[executable] +path=/home/victor/git/ctools/lang/debug +arguments= +ask_directory=1 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d6d1dd3 --- /dev/null +++ b/Makefile @@ -0,0 +1,78 @@ +SRCDIR := src +COREDIR := $(SRCDIR)/core +MATHDIR := $(COREDIR)/math +STRDIR := $(COREDIR)/string +PRINTDIR := $(COREDIR)/print +MEMDIR := $(COREDIR)/mem +SYSCALLDIR := $(COREDIR)/syscall +FILEDIR := $(COREDIR)/file +PARSEDIR := $(SRCDIR)/parse + +# Define source files +MATHSRC := $(addprefix $(MATHDIR)/, $(addsuffix .s, \ + operators \ + )) +STRSRC := $(addprefix $(STRDIR)/, $(addsuffix .s, \ + strlen split strcpy substr is_num strcmp\ + )) +MEMSRC := $(addprefix $(MEMDIR)/, $(addsuffix .s, \ + malloc memchr \ + )) +PRINTSRC := $(addprefix $(PRINTDIR)/, $(addsuffix .s, \ + print putnumber \ + )) +FILESRC := $(addprefix $(FILEDIR)/, $(addsuffix .s, \ + read_file get_file_content \ + )) +SYSCALLSRC := $(addprefix $(SYSCALLDIR)/, $(addsuffix .s, \ + exit file_ops syscall_err\ + )) +PARSESRC := $(addprefix $(PARSEDIR)/, $(addsuffix .s, \ + parse debug_token create_expressions expression debug_expression \ + )) + +# Collect all source files - now using the file variables, not directory variables +SRC := $(SRCDIR)/start.s $(MATHSRC) $(STRSRC) $(PRINTSRC) $(FILESRC) $(PARSESRC) $(SYSCALLSRC) $(MEMSRC) + +OBJDIR := obj +OBJ := $(patsubst %.s,$(OBJDIR)/%.o,$(notdir $(SRC))) + +all: debug + +debug: $(OBJDIR) $(OBJ) + ld -o $@ $(OBJ) -nostdlib -static + +# Pattern rules for object files - added the missing rules for string and print +$(OBJDIR)/%.o: $(SRCDIR)/%.s + nasm -felf64 -F dwarf -g $< -o $@ + +$(OBJDIR)/%.o: $(MATHDIR)/%.s + nasm -felf64 -F dwarf -g $< -o $@ + +$(OBJDIR)/%.o: $(STRDIR)/%.s + nasm -felf64 -F dwarf -g $< -o $@ + +$(OBJDIR)/%.o: $(MEMDIR)/%.s + nasm -felf64 -F dwarf -g $< -o $@ + +$(OBJDIR)/%.o: $(SYSCALLDIR)/%.s + nasm -felf64 -F dwarf -g $< -o $@ + +$(OBJDIR)/%.o: $(PRINTDIR)/%.s + nasm -felf64 -F dwarf -g $< -o $@ + +$(OBJDIR)/%.o: $(FILEDIR)/%.s + nasm -felf64 -F dwarf -g $< -o $@ + +$(OBJDIR)/%.o: $(PARSEDIR)/%.s + nasm -felf64 -F dwarf -g $< -o $@ + +$(OBJDIR): + mkdir -p $@ + +clean: + rm -rf $(OBJDIR) debug + +re: clean all + +.PHONY: all clean re diff --git a/src/core/file/get_file_content.s b/src/core/file/get_file_content.s new file mode 100644 index 0000000..896b030 --- /dev/null +++ b/src/core/file/get_file_content.s @@ -0,0 +1,17 @@ +section .text + global get_file_content + extern open + extern read_file + extern close + +get_file_content: ; rax: char *(rdi: char*) + mov rsi, 0 + call open + mov rdi, rax + push rax + call read_file + mov rsi, rax + pop rdi + call close + mov rax, rsi + ret diff --git a/src/core/file/read_file.s b/src/core/file/read_file.s new file mode 100644 index 0000000..ae65682 --- /dev/null +++ b/src/core/file/read_file.s @@ -0,0 +1,48 @@ + +section .text + global read_file + extern err_lseek + extern err_malloc + extern malloc + extern read + extern lseek + extern get_file_size + +read_file: ; rax: char * (rdi: int fd) + push rbp + mov rbp, rsp + sub rsp, 32 + + mov [rbp - 24], rdi ; fd + call get_file_size + + inc rax + mov [rbp - 8], rax + + mov rdi, rax + call malloc + cmp rax, 0 + jz err_malloc + + mov [rbp - 16], rax + + mov rdi, [rbp - 24] + mov rsi, 0 + mov rdx, 0 + call lseek + + cmp rax, 0 + jnz err_lseek + + mov rdi, [rbp - 24] + mov rdx, [rbp - 8] + mov rsi, [rbp - 16] + call read + + mov byte [rsi + rax], 0 + + mov rsp, rbp + pop rbp + + mov rax, rsi + ret diff --git a/src/core/math/operators.s b/src/core/math/operators.s new file mode 100644 index 0000000..e69de29 diff --git a/src/core/mem/malloc.s b/src/core/mem/malloc.s new file mode 100644 index 0000000..3688f44 --- /dev/null +++ b/src/core/mem/malloc.s @@ -0,0 +1,88 @@ +section .data + heap_break: dq 0 + heap_start: dq 0 + failure: db "[MALLOC] ERROR rax address: ", 0 + success: db "[MALLOC] INFO new address: ", 0 + str_allocated: db " allocated ", 0 + str_bytecnt: db " bytes", 0 + rdi_addr: db "rdx address: " + +section .text + global malloc + global brk_find_break + + extern putstr + extern putchar + extern putnumber + extern putendl + +brk_find_break: ; RAX: long brk(0) + mov rdi, 0x0 + mov rax, 0xC ; sys_brk + syscall + ret + +malloc: ; RAX: long basic_malloc(RDI: size_t n) + push rbx + mov rbx, rdi + mov r8, [heap_break] + cmp r8, 0 + jne .allocate ; allocate normally if exists + + call brk_find_break + mov [heap_start], rax ; get heap beginning + mov [heap_break], rax ; get heap beginning + +.allocate: + add rbx, 7 + and rbx, ~7 + + mov rdi, [heap_break] + add rdi, rbx + + mov rax, 0xC ; sys_brk + syscall + + cmp rax, rdi + jne .print_failure + + mov [heap_break], rax + mov r8, rdi + push rdi + + mov rdi, success + call putstr + mov rdi, r8 + call putnumber + + mov rdi, str_allocated + call putstr + + mov rdi, rbx + call putnumber + mov rdi, str_bytecnt + call putendl + + pop rax + sub rax, rbx + pop rbx + + ret + +.print_failure: + push rdi + mov rdi, failure + call putstr + mov rdi, rax + call putnumber + mov rdi, 0xa + call putchar + mov rdi, rdi_addr + call putstr + pop rdi + call putnumber + + xor rax, rax ; Return NULL on failure + pop rbx + + ret diff --git a/src/core/mem/memchr.s b/src/core/mem/memchr.s new file mode 100644 index 0000000..2afd675 --- /dev/null +++ b/src/core/mem/memchr.s @@ -0,0 +1,31 @@ +global memchr + +section .text + +memchr: ; rax: void *(rdi: void *, rsi: int find, rdx: size_t size) + cmp rdi, 0 + je .fail + + cmp rdx, 0 + je .no_size + + xor rcx, rcx +.loop: + cmp byte [rdi + rcx], sil + je .done + cmp byte [rdi + rcx], 0 + je .done + inc rcx + jmp .loop + +.fail: + xor rax, rax + ret + +.no_size: + mov rax, rdi + ret + +.done: + lea rax, [rdi + rcx] + ret diff --git a/src/core/print/print.s b/src/core/print/print.s new file mode 100644 index 0000000..306171e --- /dev/null +++ b/src/core/print/print.s @@ -0,0 +1,58 @@ + +section .text + extern strlen + global putstr + global putchar + global print_split + global putendl + +print_split: ; print_split(rdi: char **) + xor rcx, rcx +.loop: + cmp qword [rdi], 0 + je .done + push rdi + mov r8, [rdi] + mov rdi, r8 + push rcx + call putendl + pop rcx + pop rdi + add rdi, 8 + inc rcx + jmp .loop +.done: + mov rax, rcx + ret + +write: ; RAX: int write(RDI: int fd, RSI: char *buf, RDX: size_t n) + mov rax, 1 ; sys_write + syscall + ret + +putchar: + sub rsp, 16 ; create stack var + mov [rsp], dil ; move lower byte of tdi into stack + mov rsi, rsp + mov rdx, 1 + mov rdi, 1 + call write + add rsp, 16 + ret + +putstr: ; print_string(RDI: char *string) + call strlen + + mov rdx, rax ; string length + mov rsi, rdi ; mov buffer + mov rdi, 1 ; stdout + + call write + + ret + +putendl: + call putstr + mov rdi, 0xa + call putchar + ret diff --git a/src/core/print/putnumber.s b/src/core/print/putnumber.s new file mode 100644 index 0000000..e25cf66 --- /dev/null +++ b/src/core/print/putnumber.s @@ -0,0 +1,49 @@ +global putnumber +global putnumberendl + +section .text + extern putchar + +putnumberendl: + call putnumber + mov rdi, 0xa + call putchar + ret + +putnumber: ; void put_number(RDI: int c) + push rbx + xor rcx, rcx + +.start: + inc rcx + cmp rdi, 10 + jl .print + push rdi + mov rax, rdi + xor rdx, rdx + mov rbx, 10 + idiv rbx + mov rdi, rax + jmp .start + +.print: + mov rax, rdi + xor rdx, rdx + mov rbx, 10 + idiv rbx + mov rdi, rdx + mov rdx, 0x30 + add rdi, rdx + push rcx + call putchar + pop rcx + dec rcx + cmp rcx, 0 + je .done + pop rdi + jmp .print + +.done: + pop rbx + xor rcx, rcx + ret diff --git a/src/core/string/is_alpha.s b/src/core/string/is_alpha.s new file mode 100644 index 0000000..e69de29 diff --git a/src/core/string/is_num.s b/src/core/string/is_num.s new file mode 100644 index 0000000..b18a007 --- /dev/null +++ b/src/core/string/is_num.s @@ -0,0 +1,31 @@ +section .text + global is_num + global is_num_str + +is_num: ; rax: bool (rdi: int c) + cmp rdi, 48 + jl not_num + cmp rdi, 57 + jg not_num + mov rax, 1 + ret +not_num: + mov rax, 0 + ret + +is_num_str: ; rax: bool (rdi: char *) + xor rcx, rcx + mov r8, rdi +.loop: + mov dil, byte [r8 + rcx] + cmp dil, 0 + je .done + call is_num + cmp rax, 0 + je not_num + inc rcx + jmp .loop + +.done: + mov rax, 1 + ret diff --git a/src/core/string/replace_all.s b/src/core/string/replace_all.s new file mode 100644 index 0000000..111ddf4 --- /dev/null +++ b/src/core/string/replace_all.s @@ -0,0 +1,4 @@ +section .text + global replace_all + +replace_all: ; rax: char *(rdi: char *, rsi: int c) diff --git a/src/core/string/split.s b/src/core/string/split.s new file mode 100644 index 0000000..60ae01d --- /dev/null +++ b/src/core/string/split.s @@ -0,0 +1,147 @@ +section .text + global split + global get_split_count + extern malloc + extern putstr + extern putnumber + extern strcpy + extern memchr + extern substr + extern strlen + +get_split_count: ; rax: uint (rdi: char **) + xor rcx, rcx +.loop: + cmp qword [rdi + rcx * 8], 0 + jz .done + inc rcx + jmp .loop +.done: + mov rax, rcx + ret + +count_splits: ; RAX: int count_splits(RDI: char *, RSI: int c) + push rbx + xor rcx, rcx + xor rbx, rbx +.loop: + cmp byte [rdi + rcx], 0 + jz .done + cmp byte [rdi + rcx], sil + jne .skip +.while_is_c: + inc rcx + cmp byte [rdi + rcx], 0 + jz .done + cmp byte [rdi + rcx], sil + jz .while_is_c + inc rbx +.skip: + inc rcx + jmp .loop +.done: + mov rax, rbx + pop rbx + inc rax + ret + +split: ; RAX: char ** split(RDI: char *, RSI: int) + push rbx + push r12 + push r13 + + push rbp + mov rbp, rsp ; save base pointer + ; int count = [ rbp - 4 ] + ; char **split = [ rbp - 8 ] + + sub rsp, 16 ; allocate local vars + mov [rbp - 8], rdi + call count_splits + mov rcx, 8 + mov rbx, rax + inc rax + mul rcx + push rdi + push rsi + mov rdi, rax + call malloc + pop rsi + pop rdi + cmp rax, 0 + je .fail + + + + mov qword [rax + rbx * 8], 0 + + mov [rbp - 16], rax + mov rcx, rax + + cmp rbx, 1 + je .no_match + + call strlen + mov r13, rax + mov r12, rdi +.loop: + mov rdi, r12 + cmp rbx, 0 + je .done + + mov rdx, r13 + push rcx + call memchr + pop rcx + xor r9, r9 + jmp .skip_matches +.after_skip: + + lea rdx, [rax] + sub rdx, rdi + sub r13, rdx + + mov r12, rax + add r12, r9 + + push rsi + push rcx + mov rsi, 0 + call substr + pop rcx + pop rsi + lea r8, [rax] + mov [rcx], r8 + add rcx, 8 + dec rbx + jmp .loop + +.fail: + xor rax, rax + jmp .cleanup +.no_match: + push rcx + call strcpy + pop rcx + mov [rcx], rax +.done: + mov rax, [rbp - 16] +.cleanup: + add rsp, 16 + mov rsp, rbp + pop rbp + pop r13 + pop r12 + pop rbx + ret + +.skip_matches: + cmp byte [rax + r9], 0 + jz .after_skip + cmp byte [rax + r9], sil + jnz .after_skip + inc r9 + dec r13 + jmp .skip_matches + + diff --git a/src/core/string/strcmp.s b/src/core/string/strcmp.s new file mode 100644 index 0000000..1aabc7d --- /dev/null +++ b/src/core/string/strcmp.s @@ -0,0 +1,57 @@ +section .text + global strcmp + +strcmp: ; rax: int (rdi: char *, rsi: char *) + ; Check for NULL pointers first + test rdi, rdi ; Check if first string is NULL + jz .handle_null + test rsi, rsi ; Check if second string is NULL + jz .handle_null + + xor rcx, rcx ; initialize counter to 0 + +.loop: + ; Load characters safely using registers + movzx r9, byte [rdi + rcx] ; load current char from first string + movzx r10, byte [rsi + rcx] ; load current char from second string + + ; Check if we've reached the end of either string + test r9, r9 ; check if we reached end of first string + jz .check_second ; if so, jump to check second string + + test r10, r10 ; check if we reached end of second string + jz .greater ; if second string ends first, first string is greater + + ; Compare the characters + cmp r9, r10 ; compare characters + jl .less ; if first char < second char, first string is less + jg .greater ; if first char > second char, first string is greater + + ; Characters are equal, continue to next character + inc rcx ; increment counter + jmp .loop ; continue loop + +.check_second: + test r10, r10 ; if first string ended, check if second ended too + jz .equal ; if both ended at same position, strings are equal + jmp .less ; if only first ended, first string is less + +.handle_null: + ; Handle NULL pointer case (implementation-dependent, could also raise error) + ; Here we'll follow standard C behavior: if both are NULL, equal; otherwise compare addresses + cmp rdi, rsi + je .equal + jl .less + jmp .greater + +.less: + mov rax, -1 ; return -1 if first string is less + ret + +.greater: + mov rax, 1 ; return 1 if first string is greater + ret + +.equal: + xor rax, rax ; return 0 if strings are equal + ret diff --git a/src/core/string/strcpy.s b/src/core/string/strcpy.s new file mode 100644 index 0000000..6fca9d6 --- /dev/null +++ b/src/core/string/strcpy.s @@ -0,0 +1,28 @@ +global strcpy + +section .text + extern malloc + extern strlen + +strcpy: ; rax: char *(rdi: char *) + push rbx + push rcx + call strlen + mov r9, rdi ; r9 contains arg + mov r8, rax + mov rdi, rax + inc rdi + call malloc + xor rcx, rcx +.loop: + cmp byte [r9 + rcx], 0 + je .done + mov bl, [r9 + rcx] + mov [rax + rcx], bl + inc rcx + jmp .loop +.done: + mov byte [rax + rcx], 0 + pop rcx + pop rbx + ret diff --git a/src/core/string/strlen.s b/src/core/string/strlen.s new file mode 100644 index 0000000..be2c76d --- /dev/null +++ b/src/core/string/strlen.s @@ -0,0 +1,16 @@ +global strlen + +section .text +strlen: ; strlen(RDI: char *str) + push rcx ; save counter + xor rcx, rcx +.loop: ; loop until '\0' character + cmp byte [rdi + rcx], 0 + jz .done + inc rcx + jmp .loop +.done: + mov rax, rcx ; mov return value to rax + pop rcx ; restore counter + ret + diff --git a/src/core/string/substr.s b/src/core/string/substr.s new file mode 100644 index 0000000..9e8a805 --- /dev/null +++ b/src/core/string/substr.s @@ -0,0 +1,47 @@ +global substr + +section .text + extern strlen + extern malloc + +substr: ; rax: char*(rdi: char*, rsi: size_t begin, rdx: size_t end) + cmp rdi, 0 + je .fail + + cmp rsi, rdx + jg .fail + + call strlen + + cmp rax, rsi + jl .fail + + cmp rax, rdx + jl .fail + + push rdi + push rsi + push rdx + mov rdi, rax + add rdi, 1 + call malloc + pop rdx + pop rsi + pop rdi + + +.loop: + cmp rsi, rdx + je .done + mov r9b, [rdi + rsi] + mov [rax + rsi], r9b + inc rsi + jmp .loop + +.done: + mov byte [rax + rdx], 0 + ret + +.fail: + xor rax, rax + ret diff --git a/src/core/syscall/exit.s b/src/core/syscall/exit.s new file mode 100644 index 0000000..5d19bb9 --- /dev/null +++ b/src/core/syscall/exit.s @@ -0,0 +1,12 @@ + +section .text + global exit + global exit_err + +exit: + mov rax, 60 + syscall + +exit_err: + mov rdi, 1 + call exit diff --git a/src/core/syscall/file_ops.s b/src/core/syscall/file_ops.s new file mode 100644 index 0000000..cf609dc --- /dev/null +++ b/src/core/syscall/file_ops.s @@ -0,0 +1,38 @@ + +section .text + global open + global close + global read + global get_file_size + global lseek + +open: ; rax: int fd (rdi: char *name, rsi: int flags) + mov rax, 2 ; sys_open + syscall + ret + +close: + mov rax, 3 ; sys_close + syscall + ret + +read: ; read(RDI: int fd, RSI: char *buffer, RDX: size_t size) + mov rax, 0 ; sys_read + syscall ; + ret + +get_file_size: ;rax: size_t(rdi: int fd) + mov rax, 8 ; sys_lseek + mov rsi, 0 ; offset 0 + mov rdx, 2 + syscall + ret + +lseek: ; rax: uint (rdi: int fd, rsi: offset, rdx: int whence) + ; whence: SEEK_SET 0 = set cursor to offset + ; SEEK_CUR 1 = set cursor to current_pos + offset + ; SEEK_END 2 = set cursor to end + ; return = current offset + mov rax, 8 + syscall + ret diff --git a/src/core/syscall/syscall_err.s b/src/core/syscall/syscall_err.s new file mode 100644 index 0000000..f1a5d65 --- /dev/null +++ b/src/core/syscall/syscall_err.s @@ -0,0 +1,26 @@ +section .data + EARGCNT: db "[ERROR] Invalid arg count: expected 1", 0xa, 0 + EMALLOC: db "[ERROR] Malloc fialed!", 0xa, 0 + ELSEEK: db "[ERROR] lseek failed!", 0xa, 0 + +section .text + global err_args + global err_malloc + global err_lseek + extern exit_err + extern putstr + +err_args: + mov rdi, EARGCNT + call putstr + jmp exit_err + +err_malloc: + mov rdi, EMALLOC + call putstr + jmp exit_err + +err_lseek: + mov rdi, ELSEEK + call putstr + jmp exit_err diff --git a/src/inc/macros.inc b/src/inc/macros.inc new file mode 100644 index 0000000..7b43970 --- /dev/null +++ b/src/inc/macros.inc @@ -0,0 +1,7 @@ +%define EXPR_SIZE 32 + +%define EXPR_TYPE 0 + +%define EXPR_TOK_CNT 8 + +%define EXPR_TOK 16 diff --git a/src/parse/create_expressions.s b/src/parse/create_expressions.s new file mode 100644 index 0000000..7f53f54 --- /dev/null +++ b/src/parse/create_expressions.s @@ -0,0 +1,121 @@ +%include "./lang/src/inc/macros.inc" + +section .text + global create_expressions + extern split + extern get_split_count + extern malloc + extern err_malloc + extern parse + extern print_tokens + extern print_expression + + +create_expressions: ; rax: exp* (rdi: char *filecontent) + push rbp + mov rbp, rsp + sub rsp, 32 ; allocate stack + + mov rsi, 0x0a + call split + + mov rdi, rax + push rdi + call get_split_count + mov [rbp - 24], rax ; store split count + inc rax + mov rcx, 8 + mul rcx + mov rdi, rax + call malloc + cmp rax, 0 + mov r14, rax + je err_malloc + + mov [rbp - 8], rax ; char *** tok + + xor rcx, rcx + pop rdi + mov r13, rdi + mov r12, [rbp - 24] + +.split_splits: + mov rsi, 0x20 + cmp rcx, r12 + je .splitting_done + mov rbx, rcx + mov rdi, [r13 + rcx * 8] + call split + mov rcx, rbx + mov rbx, [rbp - 8] + mov [rbx + rcx * 8], rax + inc rcx + jmp .split_splits + +.splitting_done: + + ; allocate expressions + mov rax, [expr_size] + mul rcx ; rcx contains the amount of splits aka expr count + mov rdi, rax + call malloc + cmp rax, 0 + je err_malloc + + mov [rbp - 16], rax ; store expr* on stack + + xor rcx, rcx +.loop_expressions: + + ; create the actual expressions + mov rbx, [rbp - 24] ; expr count + cmp rcx, rbx + je .expressions_done + mov rbx, [rbp - 8] + mov rdi, [rbx + rcx * 8] + push rcx + push rdi + call get_split_count + pop rdi + push rax + + call parse + pop rdi + pop rcx + push rax + mov rbx, [rbp - 16] ; mov expr* into rax + mov rax, EXPR_SIZE + mul rcx + lea rax, [rbx + rax] + pop rbx + mov rdx, [expr_tok] + mov [rax + rdx], rbx + mov rdx, [expr_tok_cnt] + mov [rax + rdx], rdi + inc rcx + jmp .loop_expressions + +.expressions_done: + ; print expressions debug + xor rcx, rcx + +.expr_loop_print: + mov rbx, [rbp - 24] + cmp rcx, rbx + je .done + mov rbx, [rbp - 16] + mov rax, EXPR_SIZE + mul rcx + lea rdi, [rbx + rax] + push rcx + call print_expression + pop rcx + inc rcx + jmp .expr_loop_print + +.done: + mov rax, [rbp - 16] + add rsp, 32 + mov rsp, rbp + pop rbp + ret diff --git a/src/parse/debug_expression.s b/src/parse/debug_expression.s new file mode 100644 index 0000000..29fb021 --- /dev/null +++ b/src/parse/debug_expression.s @@ -0,0 +1,30 @@ +section .data + header: db 0xa, "---------", 0xa, "Expr ", 0xa, "---------", 0 + type: db 0xa, "type: ", 0 +section .text + extern print_tokens + extern expr_type + extern expr_tok + extern expr_tok_cnt + extern putendl + +global print_expression +print_expression: ; (rdi: expr*) + push r12 + push rbx + + push rdi + mov rdi, header + call putendl + pop rdi + + mov rbx, [expr_tok_cnt] + mov rsi, [rdi + rbx] + add rdi, [expr_tok] ; tok** + mov r12, [rdi] ; r12 = tok* + mov rdi, r12 + call print_tokens + + pop rbx + pop r12 + ret diff --git a/src/parse/debug_token.s b/src/parse/debug_token.s new file mode 100644 index 0000000..0ef5f21 --- /dev/null +++ b/src/parse/debug_token.s @@ -0,0 +1,76 @@ +section .data + token: db 0xa, "Token ", 0 + type: db "type = ", 0 + value: db "value = ", 0 + +section .text + global print_tokens + extern putstr + extern putendl + extern putchar + extern putnumberendl + extern get_split_count + + + +; struct token +; .type 0 +; .value +8 + +print_tokens: ; (rdi: tok*, rsi: tok_count) + push rbp + mov rbp, rsp + + sub rsp, 16 + + push r12 + push r13 + push r14 + push rbx + + mov r14, rsi + + mov [rbp - 8], rdi + + mov rbx, rdi + xor rcx, rcx +.loop: + cmp rcx, r14 + je .done + mov r12, rcx + mov rdi, token + call putstr + mov rdi, r12 + call putnumberendl + + mov rdi, type + call putstr + mov rax, 16 + mul r12 + mov rbx, [rbp - 8] + lea r13, [rbx + rax] + mov rdi, [r13] + push rax + call putnumberendl + + mov rdi, value + call putstr + pop rax + + mov rbx, [rbp - 8] + lea r13, [rbx + rax] + mov rdi, [r13 + 8] + + call putendl + mov rcx, r12 + inc rcx + jmp .loop + +.done: + pop rbx + pop r14 + pop r13 + pop r12 + mov rsp, rbp + pop rbp + ret diff --git a/src/parse/expression.s b/src/parse/expression.s new file mode 100644 index 0000000..5af749c --- /dev/null +++ b/src/parse/expression.s @@ -0,0 +1,9 @@ +section .data + + +%define EXPR_SIZE 32 + +; struct expression size = 32 +; .type +; .tok_count + 8 +; .tokens + 16 diff --git a/src/parse/lexer.s b/src/parse/lexer.s new file mode 100644 index 0000000..4689d9e --- /dev/null +++ b/src/parse/lexer.s @@ -0,0 +1,8 @@ +section .text + +; struct lexer +; .cnt 0 +; .expr* 8 + +global lex +lex: ; (rdi: expr*, rsi: cnt) diff --git a/src/parse/parse.s b/src/parse/parse.s new file mode 100644 index 0000000..fd8d63e --- /dev/null +++ b/src/parse/parse.s @@ -0,0 +1,129 @@ +%define SIZE_TOK 16 +%define TOK_ASSIGN 0 +%define TOK_ADD 1 +%define TOK_PRINT 2 +%define TOK_VAR 3 +%define TOK_CONST 4 + +section .data + OP_ASSIGN: db "=", 0 + OP_ADD: db "+", 0 + OP_PRINT: db "print", 0 + +section .text + global parse + extern strcmp + extern malloc + extern err_malloc + extern is_num_str + extern putendl + extern putnumberendl + extern get_split_count + + +; struct token +; .type 0 +; .value +8 + + +token_alloc: ; rax: tok* (rdi: int cnt) + mov rax, rdi + mov rdi, SIZE_TOK + mul rdi + mov rdi, rax + call malloc + cmp rax, 0 + je err_malloc + ret + +parse: ; rax: tok* (rdi: char**) + push rbp + mov rbp, rsp + sub rsp, 16 + mov [rbp - 8], rdi + + push r12 + push rbx + call get_split_count + mov r12, rax + mov rdi, rax + + call token_alloc + mov [rbp - 16], rax ; store token array in stack + + xor rcx, rcx +.loop: + push rcx + mov rdi, [rbp - 8] + mov rdi, [rdi + rcx * 8] + cmp qword rdi, 0 + je .done + + mov rsi, OP_ASSIGN + call strcmp + cmp rax, 0 + je .is_assign + mov rsi, OP_ADD + call strcmp + cmp rax, 0 + je .is_add + mov rsi, OP_PRINT + call strcmp + cmp rax, 0 + je .is_print + push rdi + call is_num_str + pop rdi + cmp rax, 1 + je .is_const + jmp .is_var + +.is_assign: + pop rcx + push rdi + mov rdi, TOK_ASSIGN + jmp .set_token + +.is_add: + pop rcx + push rdi + mov rdi, TOK_ADD + jmp .set_token + +.is_print: + pop rcx + push rdi + mov rdi, TOK_PRINT + jmp .set_token + +.is_const: + pop rcx + push rdi + mov rdi, TOK_CONST + jmp .set_token + +.is_var: + pop rcx + push rdi + mov rdi, TOK_VAR + jmp .set_token + +.set_token: + mov r8, [rbp - 16] + mov rax, SIZE_TOK + mul rcx + mov [r8 + rax], rdi + pop rdi + mov [r8 + rax + 8], rdi + inc rcx + jmp .loop + +.done: + pop rcx + mov rax, [rbp - 16] + pop rbx + pop r12 + mov rsp, rbp + pop rbp + ret + diff --git a/src/start.s b/src/start.s new file mode 100644 index 0000000..b237b6a --- /dev/null +++ b/src/start.s @@ -0,0 +1,51 @@ +section .data + + usage: db "Usage: ./debug .lang", 0xa, 0 +section .text + global _start + extern exit + extern split + extern print_split + extern putchar + extern putstr + extern putnumber + extern open + extern close + extern read + extern get_file_size + extern malloc + extern lseek + extern read_file + extern err_args + extern putendl + extern parse + extern print_tokens + extern err_malloc + extern get_file_content + extern create_expressions + +print_usage: + mov rdi, usage + call putstr + +_start: + pop rdi + cmp rdi, 2 + jne err_args + mov rdi, [rsp + 8] ; argv[1] + push rbp + mov rbp, rsp + + sub rsp, 16 + + call get_file_content + mov rdi, rax + call create_expressions + mov [rbp - 8], rax + + mov rsp, rbp + pop rbp + +done: + xor rdi, rdi + call exit diff --git a/test.c b/test.c new file mode 100644 index 0000000..aa93ac2 --- /dev/null +++ b/test.c @@ -0,0 +1,11 @@ +#include +#include +#include "../libft/libft.h" + +int main(int argc, char **argv) { + ft_split(argv[1], *argv[2]); + for (int i = 0; i < 2; i++) + { + write(1, argv[i + 1], strlen(argv[i + 1])); + } +} diff --git a/test.lang b/test.lang new file mode 100644 index 0000000..60bfbb4 --- /dev/null +++ b/test.lang @@ -0,0 +1,4 @@ +a = 5 +b = a + 6 +print b +b = a + a