--- /dev/null
+;; Core functions
+;;
+;;
+
+section .text
+
+;; Adds a list of numbers, address in RSI
+;; Returns the sum as a number object with address in RAX
+;; Since most of the code is common to all operators,
+;; RBX is used to jump to the required instruction
+core_add:
+ mov rbx, core_arithmetic.do_addition
+ jmp core_arithmetic
+core_sub:
+ mov rbx, core_arithmetic.do_subtraction
+ jmp core_arithmetic
+core_mul:
+ mov rbx, core_arithmetic.do_multiply
+ jmp core_arithmetic
+core_div:
+ mov rbx, core_arithmetic.do_division
+ ; Fall through to core_arithmetic
+core_arithmetic:
+ ; Check that the first object is a number
+ mov cl, BYTE [rsi]
+ mov ch, cl
+ and ch, block_mask
+ cmp ch, block_cons
+ jne .error
+ mov ch, cl
+ and ch, content_mask
+ cmp ch, content_int
+ jne .error
+
+ ; Put the starting value in rax
+ mov rax, [rsi + Cons.car]
+
+.add_loop:
+ ; Fetch the next value
+ mov cl, [rsi + Cons.typecdr]
+ cmp cl, content_nil
+ je .finished ; Nothing let
+ cmp cl, content_pointer
+ jne .error
+
+ mov rsi, [rsi + Cons.cdr] ; Get next cons
+
+ ; Check that it is an integer
+ mov cl, BYTE [rsi]
+ and cl, content_mask
+ cmp cl, content_int
+ jne .error
+
+ ; Jump to the required operation, address in RBX
+ jmp rbx
+
+.do_addition:
+ add rax, [rsi + Cons.car]
+ jmp .add_loop
+.do_subtraction:
+ sub rax, [rsi + Cons.car]
+ jmp .add_loop
+.do_multiply:
+ imul rax, [rsi + Cons.car]
+ jmp .add_loop
+.do_division:
+ xor rdx, rdx ; Zero high bits
+ mov rcx, [rsi + Cons.car]
+ idiv rcx
+ jmp .add_loop
+
+.finished:
+ ; Value in rbx
+ push rax
+ ; Get a Cons object to put the result into
+ call alloc_cons
+ pop rbx
+ mov [rax], BYTE maltype_integer
+ mov [rax + Cons.car], rbx
+ ret
+.error:
+ ; Return nil
+ call alloc_cons
+ mov [rax], BYTE maltype_nil
+ mov [rax + Cons.typecdr], BYTE content_nil
+ ret
--- /dev/null
+;;
+;; nasm -felf64 step1_read_print.asm && ld step1_read_print.o && ./a.out
+
+;; Calling convention: Address of input is in RSI
+;; Address of return value is in RAX
+;;
+
+global _start
+
+%include "types.asm" ; Data types, memory
+%include "system.asm" ; System calls
+%include "reader.asm" ; String -> Data structures
+%include "core.asm" ; Core functions
+%include "printer.asm" ; Data structures -> String
+
+section .data
+
+test_string1: db 10, "test1", 10
+.len: equ $ - test_string1
+
+test_string2: db 10, "test2", 10
+.len: equ $ - test_string2
+
+;str: ISTRUC Array
+;AT Array.type, db maltype_string
+;AT Array.length, dd 6
+;AT Array.data, db 'hello',10
+;IEND
+
+test_cons: ISTRUC Cons
+AT Cons.typecar, db ( maltype_integer + 2 )
+AT Cons.typecdr, db 0
+AT Cons.car, dq 123
+IEND
+
+test_cons2: ISTRUC Cons
+AT Cons.typecar, db ( maltype_integer + 2 )
+AT Cons.typecdr, db content_pointer
+AT Cons.car, dq 456
+AT Cons.cdr, dq test_cons
+IEND
+
+;; ------------------------------------------
+;; Fixed strings for printing
+
+prompt_string: db 10,"user> " ; The string to print at the prompt
+.len: equ $ - prompt_string
+
+section .text
+
+;; Evaluates a form
+eval:
+ mov rax, rsi ; Return the input
+ ret
+
+;; Prints the result
+print:
+ mov rax, rsi ; Return the input
+ ret
+
+;; Read-Eval-Print in sequence
+rep_seq:
+ call read_str
+ mov rsi, rax ; Output of read into input of eval
+ call eval
+ mov rsi, rax ; Output of eval into input of print
+ call print
+ mov rsi, rax ; Return value
+ ret
+
+
+_start:
+
+ ; -----------------------------
+ ; Main loop
+
+.mainLoop:
+ ; print the prompt
+ mov rdx, prompt_string.len ; number of bytes
+ mov rsi, prompt_string ; address of raw string to output
+ call print_rawstring
+
+ call read_line
+
+ ; Check if we have a zero-length string
+ cmp DWORD [rax+Array.length], 0
+ je .mainLoopEnd
+
+ push rax ; Save address of the string
+
+ ; Put into read_str
+ mov rsi, rax
+ call read_str
+ push rax
+
+ ; Add together
+ mov rsi, rax
+ call core_add
+
+ ; Put into pr_str
+ mov rsi, rax
+ call pr_str
+ push rax
+
+ mov rsi, rax ; Put into input of print_string
+ call print_string
+
+ ; Release string from pr_str
+ pop rsi
+ call release_array
+
+ ; Release the object from read_str
+ pop rsi
+ call release_object ; Could be Cons or Array
+
+ ; Release the string
+ pop rsi
+ call release_array
+
+ jmp .mainLoop
+.mainLoopEnd:
+
+ jmp quit
+