@@ 0,0 1,108 @@
+; 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
+
+ ; TODO: store value into intern table
+ ; TODO: push symbol value onto stack
+ ; TODO: bootstrap
+ ; TODO: jit self
+
+ ;; 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