+forth_asm PUT_BYTE, 'C!'
+ pop rbx
+ pop rax ; Value
+ mov [rbx], al
+ next
+
+forth_asm GET_BYTE, 'C@'
+ pop rax
+ movzx rax, byte [rax]
+ push rax
+ next
+
+;; Add two integers on the stack.
+forth_asm PLUS, '+'
+ pop rax
+ pop rbx
+ add rax, rbx
+ push rax
+ next
+
+;; Calculate difference between two integers on the stack. The second number is
+;; subtracted from the first.
+forth_asm MINUS, '-'
+ pop rax
+ pop rbx
+ sub rbx, rax
+ push rbx
+ next
+
+;; Given two integers a and b on the stack, pushes the quotient and remainder of
+;; division of a by b.
+forth_asm TIMESMOD, '/MOD'
+ pop rbx ; b
+ pop rax ; a
+ mov rdx, 0
+ div rbx
+ push rax ; a / b
+ push rdx ; a % b
+ next
+
+;; Read user input until next " character is found. Push a string containing the
+;; input on the stack as (buffer length). Note that the buffer is only valid
+;; until the next call to S" and that no more than 255 character can be read.
+forth_asm READ_STRING, 'S"'
+ push rsi
+
+ mov [.length], 0
+
+.read_char:
+ mov rax, 0
+ mov rdi, 0
+ mov rsi, .char_buffer
+ mov rdx, 1
+ syscall
+
+ mov al, [.char_buffer]
+ cmp al, '"'
+ je .done
+
+ mov rdx, .buffer
+ add rdx, [.length]
+ mov [rdx], al
+ inc [.length]
+ jmp .read_char
+
+.done:
+ pop rsi
+
+ push .buffer
+ push [.length]
+
+ next
+
+;; CREATE inserts a new header in the dictionary, and updates LATEST so that it
+;; points to the header. To compile a word, the user can then call ',' to
+;; continue to append data after the header.
+;;
+;; It takes the name of the word as a string (address length) on the stack.
+forth_asm CREATE, 'CREATE'
+ pop rcx ; Word string length
+ pop rdx ; Word string pointer
+
+ mov rdi, [here] ; rdi = Address at which to insert this entry
+ mov rax, [latest_entry] ; rax = Address of the previous entry
+ mov [rdi], rax ; Insert link to previous entry
+ mov [latest_entry], rdi ; Update LATEST to point to this word
+
+ add rdi, 8
+ mov [rdi], byte 0 ; Insert immediate flag
+
+ add rdi, 1
+ mov [rdi], byte cl ; Insert length
+
+ ;; Insert word string
+ add rdi, 1
+
+ push rsi
+ mov rsi, rdx ; rsi = Word string pointer
+ rep movsb
+ pop rsi
+
+ ;; Update HERE
+ mov [here], rdi
+
+ next
+
+forth_asm TICK, "'"
+ lodsq
+ push rax
+ next
+
+forth_asm ROT, 'ROT'
+ pop rax
+ pop rbx
+ pop rdx
+ push rax
+ push rdx
+ push rbx
+ next
+
+forth_asm PICK, 'PICK'
+ pop rax
+ lea rax, [rsp + 8 * rax]
+ mov rax, [rax]
+ push rax
+ next
+
+forth_asm EQL, '='
+ pop rax
+ pop rbx
+ cmp rax, rbx
+ je .eq
+.noteq:
+ push 0
+ next
+.eq:
+ push 1
+ next
+
+forth MAIN, 'MAIN'
+ dq INTERPRET
+ dq BRANCH, -8 * 2
+ dq TERMINATE
+
+;; Built-in variables:
+