~nch/onward

443c3d500cb9acf0f8e11d265914776106afe8bd — nc 4 years ago 30a8418
named project
2 files changed, 2 insertions(+), 105 deletions(-)

D forth.s
M makefile
D forth.s => forth.s +0 -103
@@ 1,103 0,0 @@
; vi: ft=nasm

; https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/

;

global _start
section .text
%define SYS_READ 0
%define SYS_WRITE 1
%define SYS_EXIT 60

%define STDIN 0
%define STDOUT 1

_start:

rep_loop:
        ;; write prompt
        mov rax, SYS_WRITE
        mov rdi, STDOUT
        mov rsi, prompt
        mov rdx, prompt_len
        syscall

        ;; read input string
        mov rax, SYS_READ
        mov rdi, STDIN
        mov rsi, in_buf
        mov rdx, buf_len
        syscall

        mov rdx, rax                ; length in rax

        cmp rdx, 0                  ; exit if empty (user sent Ctrl-D)
        jz exit

        ;; get the first word in the string
        ;; while calculating hash of string

        ; update hash (sdbm hash):
        ;   for c in str:
        ;     new_hash = c + (hash << 6) + (hash << 16) - hash
        ;     hash = new_hash

        mov rbx, word_buf           ; word_ptr:   rbx = (char *) word_buf
        mov rcx, 0                  ; hash:       rcx = 0
                                    ; in_buf_ptr: rsi (set above)

read_next_word_loop:
        mov rax, 0                  ; clear rax
        mov al, [rsi]               ; c = *in_buf_ptr
        cmp al, byte ' '            ; check for whitespace
        je .end
        cmp al, byte `\n`
        je .end
        cmp al, byte `\t`
        je .end
        mov [rbx], al               ; *word_buf = c

        ; rdx = new_hash (copy of hash for iteration)
        ; rax = current character (because of al)

        ; calculate hash
        mov rdx, rcx                ; rdx = hash. copied so we can shift it around
        sal rdx, 6                  ; hash << 6
        add rax, rdx
        sal rdx, 10                 ; hash << 16
        add rax, rdx
        sub rax, rcx                ; - hash
        mov rcx, rax                ; hash = new_hash

        add rsi, 1                  ; in_buf_ptr++
        add rbx, 1                  ; word_ptr++
        jmp read_next_word_loop
.end:
        ; calculate len, store it in rdx
        mov rdx, rbx
        sub rdx, word_buf

        ;; echo word
        mov rax, SYS_WRITE
        mov rdi, STDOUT
        mov rsi, word_buf
        ; rdx set above
        syscall

        jmp rep_loop

exit:
        mov rax, SYS_EXIT
        mov rdi, 0
        syscall

section .bss
        in_buf: resb 128
        buf_len: equ $ - in_buf

        word_buf: resb 32

section .rodata
        prompt: db "> "
        prompt_len: equ $ - prompt

M makefile => makefile +2 -2
@@ 1,2 1,2 @@
all:
	nasm -f elf64 -o forth.o forth.s && ld -o forth forth.o
onward: onward.s
	nasm -f elf64 -o onward.o onward.s && ld -o onward onward.o