From cbb9292fdb71a865339a13056c531be4ad99563e Mon Sep 17 00:00:00 2001 From: Mike Lowis Date: Mon, 15 Jul 2024 16:30:02 -0400 Subject: [PATCH] started writing assembly words --- Moving_Forth.pdf | Bin 0 -> 201551 bytes asm.rb | 281 +++++- asm.s | 10 + jonesforth.S | 2314 ++++++++++++++++++++++++++++++++++++++++++++++ test.c | 42 +- 5 files changed, 2595 insertions(+), 52 deletions(-) create mode 100644 Moving_Forth.pdf create mode 100644 jonesforth.S diff --git a/Moving_Forth.pdf b/Moving_Forth.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b8a218029d0a77d96c61f6bb98cd9d2430db341e GIT binary patch literal 201551 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

1uuFcdPDc|0S+otX*|+S=Ozeq9V53YkQv> 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

ulf(n)G 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

$E&l~EAQW9k#BCNEOIHmqAgNNOHAPA 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 literal 0 HcmV?d00001 diff --git a/asm.rb b/asm.rb index eb0362c..ee5ec04 100755 --- a/asm.rb +++ b/asm.rb @@ -1,21 +1,21 @@ #!/bin/env ruby PROG = [ - 0x7F, 0x45, 0x4C, 0x46, 0x02, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x3E, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # e_entry: 0x0x00400078, (virtual memory address of entry point) - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, - 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # p_vaddr: 0x0x00400000, (virtual address of segment in memory) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # p_filesz: 0x0x00011E02, (size in bytes of the segment in the file) - 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x00, 0x00, # p_memsz: 0x0x7FC00000, (size in bytes of the segment in memory) - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0x45, 0x4C, 0x46, 0x02, 0x01, 0x01, 0x00, # 00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 08 + 0x02, 0x00, 0x3E, 0x00, 0x01, 0x00, 0x00, 0x00, # 16 + 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 24 e_entry: 0x0x00400078, (virtual memory address of entry point) + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 32 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 40 + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, # 48 + 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 56 + 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, # 64 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 72 + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 78 p_vaddr: 0x00400000, (virtual address of segment in memory) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 86 + 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 94 p_filesz: 0x00011E02, (size in bytes of the segment in the file) + 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x00, 0x00, # 102 p_memsz: 0x7FC00000, (size in bytes of the segment in memory) + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 112 # 0x48, 0xc7, 0xc0, 0x3C, 0x00, 0x00, 0x00, # mov $0x3c,%rax # 0x48, 0x31, 0xff, # xor %rdi,%rdi @@ -37,23 +37,123 @@ def builtin(name, &code) $words[name] = Word.new(name, 0, code) end - +$input = $stdin $stack = [] $state = 0 $curr = nil -$buffer = [] +$buffer = "" $words = { - 'load-imm' => lambda { - puts "load-imm" - PROG.push(0x48) - PROG.push(0xc7) - PROG.push(0xC0 + $stack.pop) - imm = $stack.pop - PROG.push((imm >> 0) & 0xff) - PROG.push((imm >> 8) & 0xff) - PROG.push((imm >> 16) & 0xff) - PROG.push((imm >> 24) & 0xff) - }, +# 'load-imm' => lambda { +# puts "load-imm" +# PROG.push(0x48) +# PROG.push(0xc7) +# PROG.push(0xC0 + $stack.pop) +# imm = $stack.pop +# PROG.push((imm >> 0) & 0xff) +# PROG.push((imm >> 8) & 0xff) +# PROG.push((imm >> 16) & 0xff) +# PROG.push((imm >> 24) & 0xff) +# }, +} + + +#------------------------------------------ +# Stack Manipulation +#------------------------------------------ +builtin('drop') { } +builtin('swap') { } +builtin('dup') { } +builtin('over') { } +builtin('rot') { } +builtin('-rot') { } + +builtin('2drop') { } +builtin('2swap') { } +builtin('2dup') { } +builtin('?dup') { } + +builtin('1+') { } +builtin('1-') { } +builtin('4+') { } +builtin('4-') { } +builtin('8+') { } +builtin('8-') { } + +#------------------------------------------ +# Aritmetic +#------------------------------------------ +builtin('+') { push(pop() + pop()) } +builtin('-') { push(pop() - pop()) } +builtin('*') { push(pop() * pop()) } +builtin('/') { push(pop() / pop()) } +builtin('%') { push(pop() % pop()) } + +#------------------------------------------ +# Comparison +#------------------------------------------ +builtin('=') { push(pop() == pop()) } +builtin('!=') { push(pop() != pop()) } +builtin('<') { push(pop() < pop()) } +builtin('>') { push(pop() > pop()) } +builtin('<=') { push(pop() <= pop()) } +builtin('>=') { push(pop() >= pop()) } + +builtin('0=') { push(pop() == 0) } +builtin('0!=') { push(pop() != 0) } +builtin('0<') { push(pop() < 0) } +builtin('0>') { push(pop() > 0) } +builtin('0<=') { push(pop() <= 0) } +builtin('0>=') { push(pop() >= 0) } + + +#------------------------------------------ +# Bitwise Operations +#------------------------------------------ +builtin('and') { push(pop() & pop()) } +builtin('or') { push(pop() || pop()) } +builtin('xor') { push(pop() ^ pop()) } +builtin('invert') { push(~pop()) } + +#------------------------------------------ +# Memory +#------------------------------------------ +#builtin('!') { } +#builtin('@') { } +#builtin('+!') { } +#builtin('-!') { } + +#builtin('b!') { } +#builtin('b@') { } +#builtin('bcopy') { } +#builtin('bmove') { } + + +#------------------------------------------ +# Variables +#------------------------------------------ +# STATE +# HERE +# LATEST +# S0 +# R0 + +#------------------------------------------ +# Constants +#------------------------------------------ +#VERSION Is the current version of this FORTH. +#R0 The address of the top of the return stack. +#DOCOL Pointer to DOCOL. +#F_IMMED The IMMEDIATE flag's actual value. +#F_HIDDEN The HIDDEN flag's actual value. +#F_LENMASK The length mask in the flags/len byte. + + +#------------------------------------------ +# Compiler +#------------------------------------------ + +builtin('#') { + $buffer = $input.gets } builtin('.') { @@ -63,28 +163,24 @@ builtin('.') { pp (["..."] + $stack[-5..-1]) end } -builtin('+') { push(pop() + pop()) } -builtin('-') { push(pop() - pop()) } -builtin('*') { push(pop() * pop()) } -builtin('/') { push(pop() / pop()) } -builtin('%') { push(pop() % pop()) } builtin('word') do if $buffer.length == 0 then - $buffer = gets.scan(/[^\s]+/).reverse + $buffer = $input.gets end - push $buffer.pop + $buffer.slice!(/^\s*/) + push $buffer.slice!(/^[^\s]+/) end builtin('create') do $curr = Word.new(pop(), 0, []) end -builtin('compile') do +builtin('[') do $state = 1 end -builtin('interpret') do +builtin(']') do $state = 0 end @@ -95,30 +191,75 @@ builtin('register') do pp $words end -word(':', IMM, %w[ - word - create - compile -]) +word(':', IMM, [ 'word', 'create', '[' ]) + +word(';', IMM, [ ']', 'register' ]) + + +#------------------------------------------ +# Assembler Words +#------------------------------------------ -word(';', IMM, %w[ - interpret - register -]) +def pack8(val) + PROG.push(val & 0xff) +end + +def pack16(val) + PROG.push((val >> 0) & 0xff) + PROG.push((val >> 8) & 0xff) +end +def pack32(val) + PROG.push((val >> 0) & 0xff) + PROG.push((val >> 8) & 0xff) + PROG.push((val >> 16) & 0xff) + PROG.push((val >> 24) & 0xff) +end +def pack64(val) + PROG.push((val >> 0) & 0xff) + PROG.push((val >> 8) & 0xff) + PROG.push((val >> 16) & 0xff) + PROG.push((val >> 24) & 0xff) + PROG.push((val >> 32) & 0xff) + PROG.push((val >> 40) & 0xff) + PROG.push((val >> 48) & 0xff) + PROG.push((val >> 56) & 0xff) +end +def packBytes(bytes) + PROG.append(*bytes) +end +#builtin("virt-address") { +# +#} +# +#builtin("entry-offset") { +# +#} +# +#builtin("segment-size") { +# +#} +# +#builtin("segment-size") { +# +#} +builtin('pack8') { pack8(pop()) } +builtin('pack16') { pack16(pop()) } +builtin('pack32') { pack32(pop()) } +builtin('pack64') { pack64(pop()) } builtin('rax') { push 0 } builtin('rcx') { push 1 } builtin('rdx') { push 2 } builtin('rbx') { push 3 } -builtin('rsi') { push 4 } -builtin('rdi') { push 5 } -builtin('rsp') { push 6 } -builtin('rbp') { push 7 } +builtin('rsp') { push 4 } +builtin('rbp') { push 5 } +builtin('rsi') { push 6 } +builtin('rdi') { push 7 } builtin('r8') { push 8 } builtin('r9') { push 9 } builtin('r10') { push 10 } @@ -128,10 +269,49 @@ builtin('r13') { push 13 } builtin('r14') { push 14 } builtin('r15') { push 15 } +builtin('push-reg') { + reg = pop() + if reg <= 7 then + pack8(0x50 | reg) + else + packBytes([0x41, 0x50 | (reg - 8)]) + end +} + +builtin('pop-reg') { + reg = pop() + if reg <= 7 then + pack8(0x58 | reg) + else + packBytes([0x41, 0x58 | (reg - 8)]) + end +} + +builtin('load-imm') { +} + +builtin('syscall') { + packBytes([0x0f, 0x05]) +} + +builtin('ret') { + pack8(0xc3) +} + +builtin('nop') { + pack8(0x90) +} + + + +#------------------------------------------ +# Input Interpreter +#------------------------------------------ loop do $words['word'].code.call() w = $stack.pop + next if w.nil? or w.length == 0 if $words[w] then if $state == 0 || (($words[w].flags & IMM) == IMM) $words[w].code.call @@ -145,6 +325,7 @@ loop do $curr.code << lambda{ push w.to_i } end else + pp $stack puts "?" $stack = [] end diff --git a/asm.s b/asm.s index e19d06a..9810106 100644 --- a/asm.s +++ b/asm.s @@ -1,3 +1,13 @@ +# Allocate space for variables +0 pack64 # STATE +0 pack64 # HERE +0 pack64 # LATEST +0 pack64 # S0 +0 pack64 # R0 + 60 rax load-imm +0 rdi load-imm +syscall + #rdi rdi xor #syscall diff --git a/jonesforth.S b/jonesforth.S new file mode 100644 index 0000000..8d23e39 --- /dev/null +++ b/jonesforth.S @@ -0,0 +1,2314 @@ +/* A sometimes minimal FORTH compiler and tutorial for Linux / i386 systems. -*- asm -*- + By Richard W.M. Jones http://annexia.org/forth + This is PUBLIC DOMAIN (see public domain release statement below). + $Id: jonesforth.S,v 1.47 2009-09-11 08:33:13 rich Exp $ + + gcc -m32 -nostdlib -static -Wl,-Ttext,0 -Wl,--build-id=none -o jonesforth jonesforth.S +*/ + .set JONES_VERSION,47 +/* + INTRODUCTION ---------------------------------------------------------------------- + + FORTH is one of those alien languages which most working programmers regard in the same + way as Haskell, LISP, and so on. Something so strange that they'd rather any thoughts + of it just go away so they can get on with writing this paying code. But that's wrong + and if you care at all about programming then you should at least understand all these + languages, even if you will never use them. + + LISP is the ultimate high-level language, and features from LISP are being added every + decade to the more common languages. But FORTH is in some ways the ultimate in low level + programming. Out of the box it lacks features like dynamic memory management and even + strings. In fact, at its primitive level it lacks even basic concepts like IF-statements + and loops. + + Why then would you want to learn FORTH? There are several very good reasons. First + and foremost, FORTH is minimal. You really can write a complete FORTH in, say, 2000 + lines of code. I don't just mean a FORTH program, I mean a complete FORTH operating + system, environment and language. You could boot such a FORTH on a bare PC and it would + come up with a prompt where you could start doing useful work. The FORTH you have here + isn't minimal and uses a Linux process as its 'base PC' (both for the purposes of making + it a good tutorial). It's possible to completely understand the system. Who can say they + completely understand how Linux works, or gcc? + + Secondly FORTH has a peculiar bootstrapping property. By that I mean that after writing + a little bit of assembly to talk to the hardware and implement a few primitives, all the + rest of the language and compiler is written in FORTH itself. Remember I said before + that FORTH lacked IF-statements and loops? Well of course it doesn't really because + such a lanuage would be useless, but my point was rather that IF-statements and loops are + written in FORTH itself. + + Now of course this is common in other languages as well, and in those languages we call + them 'libraries'. For example in C, 'printf' is a library function written in C. But + in FORTH this goes way beyond mere libraries. Can you imagine writing C's 'if' in C? + And that brings me to my third reason: If you can write 'if' in FORTH, then why restrict + yourself to the usual if/while/for/switch constructs? You want a construct that iterates + over every other element in a list of numbers? You can add it to the language. What + about an operator which pulls in variables directly from a configuration file and makes + them available as FORTH variables? Or how about adding Makefile-like dependencies to + the language? No problem in FORTH. How about modifying the FORTH compiler to allow + complex inlining strategies -- simple. This concept isn't common in programming languages, + but it has a name (in fact two names): "macros" (by which I mean LISP-style macros, not + the lame C preprocessor) and "domain specific languages" (DSLs). + + This tutorial isn't about learning FORTH as the language. I'll point you to some references + you should read if you're not familiar with using FORTH. This tutorial is about how to + write FORTH. In fact, until you understand how FORTH is written, you'll have only a very + superficial understanding of how to use it. + + So if you're not familiar with FORTH or want to refresh your memory here are some online + references to read: + + http://en.wikipedia.org/wiki/Forth_%28programming_language%29 + + http://galileo.phys.virginia.edu/classes/551.jvn.fall01/primer.htm + + http://wiki.laptop.org/go/Forth_Lessons + + http://www.albany.net/~hello/simple.htm + + Here is another "Why FORTH?" essay: http://www.jwdt.com/~paysan/why-forth.html + + Discussion and criticism of this FORTH here: http://lambda-the-ultimate.org/node/2452 + + ACKNOWLEDGEMENTS ---------------------------------------------------------------------- + + This code draws heavily on the design of LINA FORTH (http://home.hccnet.nl/a.w.m.van.der.horst/lina.html) + by Albert van der Horst. Any similarities in the code are probably not accidental. + + Some parts of this FORTH are also based on this IOCCC entry from 1992: + http://ftp.funet.fi/pub/doc/IOCCC/1992/buzzard.2.design. + I was very proud when Sean Barrett, the original author of the IOCCC entry, commented in the LtU thread + http://lambda-the-ultimate.org/node/2452#comment-36818 about this FORTH. + + And finally I'd like to acknowledge the (possibly forgotten?) authors of ARTIC FORTH because their + original program which I still have on original cassette tape kept nagging away at me all these years. + http://en.wikipedia.org/wiki/Artic_Software + + PUBLIC DOMAIN ---------------------------------------------------------------------- + + I, the copyright holder of this work, hereby release it into the public domain. This applies worldwide. + + In case this is not legally possible, I grant any entity the right to use this work for any purpose, + without any conditions, unless such conditions are required by law. + + SETTING UP ---------------------------------------------------------------------- + + Let's get a few housekeeping things out of the way. Firstly because I need to draw lots of + ASCII-art diagrams to explain concepts, the best way to look at this is using a window which + uses a fixed width font and is at least this wide: + + <------------------------------------------------------------------------------------------------------------------------> + + Secondly make sure TABS are set to 8 characters. The following should be a vertical + line. If not, sort out your tabs. + + | + | + | + + Thirdly I assume that your screen is at least 50 characters high. + + ASSEMBLING ---------------------------------------------------------------------- + + If you want to actually run this FORTH, rather than just read it, you will need Linux on an + i386. Linux because instead of programming directly to the hardware on a bare PC which I + could have done, I went for a simpler tutorial by assuming that the 'hardware' is a Linux + process with a few basic system calls (read, write and exit and that's about all). i386 + is needed because I had to write the assembly for a processor, and i386 is by far the most + common. (Of course when I say 'i386', any 32- or 64-bit x86 processor will do. I'm compiling + this on a 64 bit AMD Opteron). + + Again, to assemble this you will need gcc and gas (the GNU assembler). The commands to + assemble and run the code (save this file as 'jonesforth.S') are: + + gcc -m32 -nostdlib -static -Wl,-Ttext,0 -Wl,--build-id=none -o jonesforth jonesforth.S + cat jonesforth.f - | ./jonesforth + + If you want to run your own FORTH programs you can do: + + cat jonesforth.f myprog.f | ./jonesforth + + If you want to load your own FORTH code and then continue reading user commands, you can do: + + cat jonesforth.f myfunctions.f - | ./jonesforth + + ASSEMBLER ---------------------------------------------------------------------- + + (You can just skip to the next section -- you don't need to be able to read assembler to + follow this tutorial). + + However if you do want to read the assembly code here are a few notes about gas (the GNU assembler): + + (1) Register names are prefixed with '%', so %eax is the 32 bit i386 accumulator. The registers + available on i386 are: %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp and %esp, and most of them + have special purposes. + + (2) Add, mov, etc. take arguments in the form SRC,DEST. So mov %eax,%ecx moves %eax -> %ecx + + (3) Constants are prefixed with '$', and you mustn't forget it! If you forget it then it + causes a read from memory instead, so: + mov $2,%eax moves number 2 into %eax + mov 2,%eax reads the 32 bit word from address 2 into %eax (ie. most likely a mistake) + + (4) gas has a funky syntax for local labels, where '1f' (etc.) means label '1:' "forwards" + and '1b' (etc.) means label '1:' "backwards". Notice that these labels might be mistaken + for hex numbers (eg. you might confuse 1b with $0x1b). + + (5) 'ja' is "jump if above", 'jb' for "jump if below", 'je' "jump if equal" etc. + + (6) gas has a reasonably nice .macro syntax, and I use them a lot to make the code shorter and + less repetitive. + + For more help reading the assembler, do "info gas" at the Linux prompt. + + Now the tutorial starts in earnest. + + THE DICTIONARY ---------------------------------------------------------------------- + + In FORTH as you will know, functions are called "words", and just as in other languages they + have a name and a definition. Here are two FORTH words: + + : DOUBLE DUP + ; \ name is "DOUBLE", definition is "DUP +" + : QUADRUPLE DOUBLE DOUBLE ; \ name is "QUADRUPLE", definition is "DOUBLE DOUBLE" + + Words, both built-in ones and ones which the programmer defines later, are stored in a dictionary + which is just a linked list of dictionary entries. + + <--- DICTIONARY ENTRY (HEADER) -----------------------> + +------------------------+--------+---------- - - - - +----------- - - - - + | LINK POINTER | LENGTH/| NAME | DEFINITION + | | FLAGS | | + +--- (4 bytes) ----------+- byte -+- n bytes - - - - +----------- - - - - + + I'll come to the definition of the word later. For now just look at the header. The first + 4 bytes are the link pointer. This points back to the previous word in the dictionary, or, for + the first word in the dictionary it is just a NULL pointer. Then comes a length/flags byte. + The length of the word can be up to 31 characters (5 bits used) and the top three bits are used + for various flags which I'll come to later. This is followed by the name itself, and in this + implementation the name is rounded up to a multiple of 4 bytes by padding it with zero bytes. + That's just to ensure that the definition starts on a 32 bit boundary. + + A FORTH variable called LATEST contains a pointer to the most recently defined word, in + other words, the head of this linked list. + + DOUBLE and QUADRUPLE might look like this: + + pointer to previous word + ^ + | + +--|------+---+---+---+---+---+---+---+---+------------- - - - - + | LINK | 6 | D | O | U | B | L | E | 0 | (definition ...) + +---------+---+---+---+---+---+---+---+---+------------- - - - - + ^ len padding + | + +--|------+---+---+---+---+---+---+---+---+---+---+---+---+------------- - - - - + | LINK | 9 | Q | U | A | D | R | U | P | L | E | 0 | 0 | (definition ...) + +---------+---+---+---+---+---+---+---+---+---+---+---+---+------------- - - - - + ^ len padding + | + | + LATEST + + You should be able to see from this how you might implement functions to find a word in + the dictionary (just walk along the dictionary entries starting at LATEST and matching + the names until you either find a match or hit the NULL pointer at the end of the dictionary); + and add a word to the dictionary (create a new definition, set its LINK to LATEST, and set + LATEST to point to the new word). We'll see precisely these functions implemented in + assembly code later on. + + One interesting consequence of using a linked list is that you can redefine words, and + a newer definition of a word overrides an older one. This is an important concept in + FORTH because it means that any word (even "built-in" or "standard" words) can be + overridden with a new definition, either to enhance it, to make it faster or even to + disable it. However because of the way that FORTH words get compiled, which you'll + understand below, words defined using the old definition of a word continue to use + the old definition. Only words defined after the new definition use the new definition. + + DIRECT THREADED CODE ---------------------------------------------------------------------- + + Now we'll get to the really crucial bit in understanding FORTH, so go and get a cup of tea + or coffee and settle down. It's fair to say that if you don't understand this section, then you + won't "get" how FORTH works, and that would be a failure on my part for not explaining it well. + So if after reading this section a few times you don't understand it, please email me + (rich@annexia.org). + + Let's talk first about what "threaded code" means. Imagine a peculiar version of C where + you are only allowed to call functions without arguments. (Don't worry for now that such a + language would be completely useless!) So in our peculiar C, code would look like this: + + f () + { + a (); + b (); + c (); + } + + and so on. How would a function, say 'f' above, be compiled by a standard C compiler? + Probably into assembly code like this. On the right hand side I've written the actual + i386 machine code. + + f: + CALL a E8 08 00 00 00 + CALL b E8 1C 00 00 00 + CALL c E8 2C 00 00 00 + ; ignore the return from the function for now + + "E8" is the x86 machine code to "CALL" a function. In the first 20 years of computing + memory was hideously expensive and we might have worried about the wasted space being used + by the repeated "E8" bytes. We can save 20% in code size (and therefore, in expensive memory) + by compressing this into just: + + 08 00 00 00 Just the function addresses, without + 1C 00 00 00 the CALL prefix. + 2C 00 00 00 + + On a 16-bit machine like the ones which originally ran FORTH the savings are even greater - 33%. + + [Historical note: If the execution model that FORTH uses looks strange from the following + paragraphs, then it was motivated entirely by the need to save memory on early computers. + This code compression isn't so important now when our machines have more memory in their L1 + caches than those early computers had in total, but the execution model still has some + useful properties]. + + Of course this code won't run directly on the CPU any more. Instead we need to write an + interpreter which takes each set of bytes and calls it. + + On an i386 machine it turns out that we can write this interpreter rather easily, in just + two assembly instructions which turn into just 3 bytes of machine code. Let's store the + pointer to the next word to execute in the %esi register: + + 08 00 00 00 <- We're executing this one now. %esi is the _next_ one to execute. + %esi -> 1C 00 00 00 + 2C 00 00 00 + + The all-important i386 instruction is called LODSL (or in Intel manuals, LODSW). It does + two things. Firstly it reads the memory at %esi into the accumulator (%eax). Secondly it + increments %esi by 4 bytes. So after LODSL, the situation now looks like this: + + 08 00 00 00 <- We're still executing this one + 1C 00 00 00 <- %eax now contains this address (0x0000001C) + %esi -> 2C 00 00 00 + + Now we just need to jump to the address in %eax. This is again just a single x86 instruction + written JMP *(%eax). And after doing the jump, the situation looks like: + + 08 00 00 00 + 1C 00 00 00 <- Now we're executing this subroutine. + %esi -> 2C 00 00 00 + + To make this work, each subroutine is followed by the two instructions 'LODSL; JMP *(%eax)' + which literally make the jump to the next subroutine. + + And that brings us to our first piece of actual code! Well, it's a macro. +*/ + +/* NEXT macro. */ + .macro NEXT + lodsl + jmp *(%eax) + .endm + +/* The macro is called NEXT. That's a FORTH-ism. It expands to those two instructions. + + Every FORTH primitive that we write has to be ended by NEXT. Think of it kind of like + a return. + + The above describes what is known as direct threaded code. + + To sum up: We compress our function calls down to a list of addresses and use a somewhat + magical macro to act as a "jump to next function in the list". We also use one register (%esi) + to act as a kind of instruction pointer, pointing to the next function in the list. + + I'll just give you a hint of what is to come by saying that a FORTH definition such as: + + : QUADRUPLE DOUBLE DOUBLE ; + + actually compiles (almost, not precisely but we'll see why in a moment) to a list of + function addresses for DOUBLE, DOUBLE and a special function called EXIT to finish off. + + At this point, REALLY EAGLE-EYED ASSEMBLY EXPERTS are saying "JONES, YOU'VE MADE A MISTAKE!". + + I lied about JMP *(%eax). + + INDIRECT THREADED CODE ---------------------------------------------------------------------- + + It turns out that direct threaded code is interesting but only if you want to just execute + a list of functions written in assembly language. So QUADRUPLE would work only if DOUBLE + was an assembly language function. In the direct threaded code, QUADRUPLE would look like: + + +------------------+ + | addr of DOUBLE --------------------> (assembly code to do the double) + +------------------+ NEXT + %esi -> | addr of DOUBLE | + +------------------+ + + We can add an extra indirection to allow us to run both words written in assembly language + (primitives written for speed) and words written in FORTH themselves as lists of addresses. + + The extra indirection is the reason for the brackets in JMP *(%eax). + + Let's have a look at how QUADRUPLE and DOUBLE really look in FORTH: + + : QUADRUPLE DOUBLE DOUBLE ; + + +------------------+ + | codeword | : DOUBLE DUP + ; + +------------------+ + | addr of DOUBLE ---------------> +------------------+ + +------------------+ | codeword | + | addr of DOUBLE | +------------------+ + +------------------+ | addr of DUP --------------> +------------------+ + | addr of EXIT | +------------------+ | codeword -------+ + +------------------+ %esi -> | addr of + --------+ +------------------+ | + +------------------+ | | assembly to <-----+ + | addr of EXIT | | | implement DUP | + +------------------+ | | .. | + | | .. | + | | NEXT | + | +------------------+ + | + +-----> +------------------+ + | codeword -------+ + +------------------+ | + | assembly to <------+ + | implement + | + | .. | + | .. | + | NEXT | + +------------------+ + + This is the part where you may need an extra cup of tea/coffee/favourite caffeinated + beverage. What has changed is that I've added an extra pointer to the beginning of + the definitions. In FORTH this is sometimes called the "codeword". The codeword is + a pointer to the interpreter to run the function. For primitives written in + assembly language, the "interpreter" just points to the actual assembly code itself. + They don't need interpreting, they just run. + + In words written in FORTH (like QUADRUPLE and DOUBLE), the codeword points to an interpreter + function. + + I'll show you the interpreter function shortly, but let's recall our indirect + JMP *(%eax) with the "extra" brackets. Take the case where we're executing DOUBLE + as shown, and DUP has been called. Note that %esi is pointing to the address of + + + The assembly code for DUP eventually does a NEXT. That: + + (1) reads the address of + into %eax %eax points to the codeword of + + (2) increments %esi by 4 + (3) jumps to the indirect %eax jumps to the address in the codeword of +, + ie. the assembly code to implement + + + +------------------+ + | codeword | + +------------------+ + | addr of DOUBLE ---------------> +------------------+ + +------------------+ | codeword | + | addr of DOUBLE | +------------------+ + +------------------+ | addr of DUP --------------> +------------------+ + | addr of EXIT | +------------------+ | codeword -------+ + +------------------+ | addr of + --------+ +------------------+ | + +------------------+ | | assembly to <-----+ + %esi -> | addr of EXIT | | | implement DUP | + +------------------+ | | .. | + | | .. | + | | NEXT | + | +------------------+ + | + +-----> +------------------+ + | codeword -------+ + +------------------+ | + now we're | assembly to <-----+ + executing | implement + | + this | .. | + function | .. | + | NEXT | + +------------------+ + + So I hope that I've convinced you that NEXT does roughly what you'd expect. This is + indirect threaded code. + + I've glossed over four things. I wonder if you can guess without reading on what they are? + + . + . + . + + My list of four things are: (1) What does "EXIT" do? (2) which is related to (1) is how do + you call into a function, ie. how does %esi start off pointing at part of QUADRUPLE, but + then point at part of DOUBLE. (3) What goes in the codeword for the words which are written + in FORTH? (4) How do you compile a function which does anything except call other functions + ie. a function which contains a number like : DOUBLE 2 * ; ? + + THE INTERPRETER AND RETURN STACK ------------------------------------------------------------ + + Going at these in no particular order, let's talk about issues (3) and (2), the interpreter + and the return stack. + + Words which are defined in FORTH need a codeword which points to a little bit of code to + give them a "helping hand" in life. They don't need much, but they do need what is known + as an "interpreter", although it doesn't really "interpret" in the same way that, say, + Java bytecode used to be interpreted (ie. slowly). This interpreter just sets up a few + machine registers so that the word can then execute at full speed using the indirect + threaded model above. + + One of the things that needs to happen when QUADRUPLE calls DOUBLE is that we save the old + %esi ("instruction pointer") and create a new one pointing to the first word in DOUBLE. + Because we will need to restore the old %esi at the end of DOUBLE (this is, after all, like + a function call), we will need a stack to store these "return addresses" (old values of %esi). + + As you will have seen in the background documentation, FORTH has two stacks, an ordinary + stack for parameters, and a return stack which is a bit more mysterious. But our return + stack is just the stack I talked about in the previous paragraph, used to save %esi when + calling from a FORTH word into another FORTH word. + + In this FORTH, we are using the normal stack pointer (%esp) for the parameter stack. + We will use the i386's "other" stack pointer (%ebp, usually called the "frame pointer") + for our return stack. + + I've got two macros which just wrap up the details of using %ebp for the return stack. + You use them as for example "PUSHRSP %eax" (push %eax on the return stack) or "POPRSP %ebx" + (pop top of return stack into %ebx). +*/ + +/* Macros to deal with the return stack. */ + .macro PUSHRSP reg + lea -4(%ebp),%ebp // push reg on to return stack + movl \reg,(%ebp) + .endm + + .macro POPRSP reg + mov (%ebp),\reg // pop top of return stack to reg + lea 4(%ebp),%ebp + .endm + +/* + And with that we can now talk about the interpreter. + + In FORTH the interpreter function is often called DOCOL (I think it means "DO COLON" because + all FORTH definitions start with a colon, as in : DOUBLE DUP + ; + + The "interpreter" (it's not really "interpreting") just needs to push the old %esi on the + stack and set %esi to the first word in the definition. Remember that we jumped to the + function using JMP *(%eax)? Well a consequence of that is that conveniently %eax contains + the address of this codeword, so just by adding 4 to it we get the address of the first + data word. Finally after setting up %esi, it just does NEXT which causes that first word + to run. +*/ + +/* DOCOL - the interpreter! */ + .text + .align 4 +DOCOL: + PUSHRSP %esi // push %esi on to the return stack + addl $4,%eax // %eax points to codeword, so make + movl %eax,%esi // %esi point to first data word + NEXT + +/* + Just to make this absolutely clear, let's see how DOCOL works when jumping from QUADRUPLE + into DOUBLE: + + QUADRUPLE: + +------------------+ + | codeword | + +------------------+ DOUBLE: + | addr of DOUBLE ---------------> +------------------+ + +------------------+ %eax -> | addr of DOCOL | + %esi -> | addr of DOUBLE | +------------------+ + +------------------+ | addr of DUP | + | addr of EXIT | +------------------+ + +------------------+ | etc. | + + First, the call to DOUBLE calls DOCOL (the codeword of DOUBLE). DOCOL does this: It + pushes the old %esi on the return stack. %eax points to the codeword of DOUBLE, so we + just add 4 on to it to get our new %esi: + + QUADRUPLE: + +------------------+ + | codeword | + +------------------+ DOUBLE: + | addr of DOUBLE ---------------> +------------------+ +top of return +------------------+ %eax -> | addr of DOCOL | +stack points -> | addr of DOUBLE | + 4 = +------------------+ + +------------------+ %esi -> | addr of DUP | + | addr of EXIT | +------------------+ + +------------------+ | etc. | + + Then we do NEXT, and because of the magic of threaded code that increments %esi again + and calls DUP. + + Well, it seems to work. + + One minor point here. Because DOCOL is the first bit of assembly actually to be defined + in this file (the others were just macros), and because I usually compile this code with the + text segment starting at address 0, DOCOL has address 0. So if you are disassembling the + code and see a word with a codeword of 0, you will immediately know that the word is + written in FORTH (it's not an assembler primitive) and so uses DOCOL as the interpreter. + + STARTING UP ---------------------------------------------------------------------- + + Now let's get down to nuts and bolts. When we start the program we need to set up + a few things like the return stack. But as soon as we can, we want to jump into FORTH + code (albeit much of the "early" FORTH code will still need to be written as + assembly language primitives). + + This is what the set up code does. Does a tiny bit of house-keeping, sets up the + separate return stack (NB: Linux gives us the ordinary parameter stack already), then + immediately jumps to a FORTH word called QUIT. Despite its name, QUIT doesn't quit + anything. It resets some internal state and starts reading and interpreting commands. + (The reason it is called QUIT is because you can call QUIT from your own FORTH code + to "quit" your program and go back to interpreting). +*/ + +/* Assembler entry point. */ + .text + .globl _start +_start: + cld + mov %esp,var_S0 // Save the initial data stack pointer in FORTH variable S0. + mov $return_stack_top,%ebp // Initialise the return stack. + call set_up_data_segment + + mov $cold_start,%esi // Initialise interpreter. + NEXT // Run interpreter! + + .section .rodata +cold_start: // High-level code without a codeword. + .int QUIT + +/* + BUILT-IN WORDS ---------------------------------------------------------------------- + + Remember our dictionary entries (headers)? Let's bring those together with the codeword + and data words to see how : DOUBLE DUP + ; really looks in memory. + + pointer to previous word + ^ + | + +--|------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+ + | LINK | 6 | D | O | U | B | L | E | 0 | DOCOL | DUP | + | EXIT | + +---------+---+---+---+---+---+---+---+---+------------+--|---------+------------+------------+ + ^ len pad codeword | + | V + LINK in next word points to codeword of DUP + + Initially we can't just write ": DOUBLE DUP + ;" (ie. that literal string) here because we + don't yet have anything to read the string, break it up at spaces, parse each word, etc. etc. + So instead we will have to define built-in words using the GNU assembler data constructors + (like .int, .byte, .string, .ascii and so on -- look them up in the gas info page if you are + unsure of them). + + The long way would be: + + .int + .byte 6 // len + .ascii "DOUBLE" // string + .byte 0 // padding +DOUBLE: .int DOCOL // codeword + .int DUP // pointer to codeword of DUP + .int PLUS // pointer to codeword of + + .int EXIT // pointer to codeword of EXIT + + That's going to get quite tedious rather quickly, so here I define an assembler macro + so that I can just write: + + defword "DOUBLE",6,,DOUBLE + .int DUP,PLUS,EXIT + + and I'll get exactly the same effect. + + Don't worry too much about the exact implementation details of this macro - it's complicated! +*/ + +/* Flags - these are discussed later. */ + .set F_IMMED,0x80 + .set F_HIDDEN,0x20 + .set F_LENMASK,0x1f // length mask + + // Store the chain of links. + .set link,0 + + .macro defword name, namelen, flags=0, label + .section .rodata + .align 4 + .globl name_\label +name_\label : + .int link // link + .set link,name_\label + .byte \flags+\namelen // flags + length byte + .ascii "\name" // the name + .align 4 // padding to next 4 byte boundary + .globl \label +\label : + .int DOCOL // codeword - the interpreter + // list of word pointers follow + .endm + +/* + Similarly I want a way to write words written in assembly language. There will be quite a few + of these to start with because, well, everything has to start in assembly before there's + enough "infrastructure" to be able to start writing FORTH words, but also I want to define + some common FORTH words in assembly language for speed, even though I could write them in FORTH. + + This is what DUP looks like in memory: + + pointer to previous word + ^ + | + +--|------+---+---+---+---+------------+ + | LINK | 3 | D | U | P | code_DUP ---------------------> points to the assembly + +---------+---+---+---+---+------------+ code used to write DUP, + ^ len codeword which ends with NEXT. + | + LINK in next word + + Again, for brevity in writing the header I'm going to write an assembler macro called defcode. + As with defword above, don't worry about the complicated details of the macro. +*/ + + .macro defcode name, namelen, flags=0, label + .section .rodata + .align 4 + .globl name_\label +name_\label : + .int link // link + .set link,name_\label + .byte \flags+\namelen // flags + length byte + .ascii "\name" // the name + .align 4 // padding to next 4 byte boundary + .globl \label +\label : + .int code_\label // codeword + .text + //.align 4 + .globl code_\label +code_\label : // assembler code follows + .endm + +/* + Now some easy FORTH primitives. These are written in assembly for speed. If you understand + i386 assembly language then it is worth reading these. However if you don't understand assembly + you can skip the details. +*/ + + defcode "DROP",4,,DROP + pop %eax // drop top of stack + NEXT + + defcode "SWAP",4,,SWAP + pop %eax // swap top two elements on stack + pop %ebx + push %eax + push %ebx + NEXT + + defcode "DUP",3,,DUP + mov (%esp),%eax // duplicate top of stack + push %eax + NEXT + + defcode "OVER",4,,OVER + mov 4(%esp),%eax // get the second element of stack + push %eax // and push it on top + NEXT + + defcode "ROT",3,,ROT + pop %eax + pop %ebx + pop %ecx + push %ebx + push %eax + push %ecx + NEXT + + defcode "-ROT",4,,NROT + pop %eax + pop %ebx + pop %ecx + push %eax + push %ecx + push %ebx + NEXT + + defcode "2DROP",5,,TWODROP // drop top two elements of stack + pop %eax + pop %eax + NEXT + + defcode "2DUP",4,,TWODUP // duplicate top two elements of stack + mov (%esp),%eax + mov 4(%esp),%ebx + push %ebx + push %eax + NEXT + + defcode "2SWAP",5,,TWOSWAP // swap top two pairs of elements of stack + pop %eax + pop %ebx + pop %ecx + pop %edx + push %ebx + push %eax + push %edx + push %ecx + NEXT + + defcode "?DUP",4,,QDUP // duplicate top of stack if non-zero + movl (%esp),%eax + test %eax,%eax + jz 1f + push %eax +1: NEXT + + defcode "1+",2,,INCR + incl (%esp) // increment top of stack + NEXT + + defcode "1-",2,,DECR + decl (%esp) // decrement top of stack + NEXT + + defcode "4+",2,,INCR4 + addl $4,(%esp) // add 4 to top of stack + NEXT + + defcode "4-",2,,DECR4 + subl $4,(%esp) // subtract 4 from top of stack + NEXT + + defcode "+",1,,ADD + pop %eax // get top of stack + addl %eax,(%esp) // and add it to next word on stack + NEXT + + defcode "-",1,,SUB + pop %eax // get top of stack + subl %eax,(%esp) // and subtract it from next word on stack + NEXT + + defcode "*",1,,MUL + pop %eax + pop %ebx + imull %ebx,%eax + push %eax // ignore overflow + NEXT + +/* + In this FORTH, only /MOD is primitive. Later we will define the / and MOD words in + terms of the primitive /MOD. The design of the i386 assembly instruction idiv which + leaves both quotient and remainder makes this the obvious choice. +*/ + + defcode "/MOD",4,,DIVMOD + xor %edx,%edx + pop %ebx + pop %eax + idivl %ebx + push %edx // push remainder + push %eax // push quotient + NEXT + +/* + Lots of comparison operations like =, <, >, etc.. + + ANS FORTH says that the comparison words should return all (binary) 1's for + TRUE and all 0's for FALSE. However this is a bit of a strange convention + so this FORTH breaks it and returns the more normal (for C programmers ...) + 1 meaning TRUE and 0 meaning FALSE. +*/ + + defcode "=",1,,EQU // top two words are equal? + pop %eax + pop %ebx + cmp %ebx,%eax + sete %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode "<>",2,,NEQU // top two words are not equal? + pop %eax + pop %ebx + cmp %ebx,%eax + setne %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode "<",1,,LT + pop %eax + pop %ebx + cmp %eax,%ebx + setl %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode ">",1,,GT + pop %eax + pop %ebx + cmp %eax,%ebx + setg %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode "<=",2,,LE + pop %eax + pop %ebx + cmp %eax,%ebx + setle %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode ">=",2,,GE + pop %eax + pop %ebx + cmp %eax,%ebx + setge %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode "0=",2,,ZEQU // top of stack equals 0? + pop %eax + test %eax,%eax + setz %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode "0<>",3,,ZNEQU // top of stack not 0? + pop %eax + test %eax,%eax + setnz %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode "0<",2,,ZLT // comparisons with 0 + pop %eax + test %eax,%eax + setl %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode "0>",2,,ZGT + pop %eax + test %eax,%eax + setg %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode "0<=",3,,ZLE + pop %eax + test %eax,%eax + setle %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode "0>=",3,,ZGE + pop %eax + test %eax,%eax + setge %al + movzbl %al,%eax + pushl %eax + NEXT + + defcode "AND",3,,AND // bitwise AND + pop %eax + andl %eax,(%esp) + NEXT + + defcode "OR",2,,OR // bitwise OR + pop %eax + orl %eax,(%esp) + NEXT + + defcode "XOR",3,,XOR // bitwise XOR + pop %eax + xorl %eax,(%esp) + NEXT + + defcode "INVERT",6,,INVERT // this is the FORTH bitwise "NOT" function (cf. NEGATE and NOT) + notl (%esp) + NEXT + +/* + RETURNING FROM FORTH WORDS ---------------------------------------------------------------------- + + Time to talk about what happens when we EXIT a function. In this diagram QUADRUPLE has called + DOUBLE, and DOUBLE is about to exit (look at where %esi is pointing): + + QUADRUPLE + +------------------+ + | codeword | + +------------------+ DOUBLE + | addr of DOUBLE ---------------> +------------------+ + +------------------+ | codeword | + | addr of DOUBLE | +------------------+ + +------------------+ | addr of DUP | + | addr of EXIT | +------------------+ + +------------------+ | addr of + | + +------------------+ + %esi -> | addr of EXIT | + +------------------+ + + What happens when the + function does NEXT? Well, the following code is executed. +*/ + + defcode "EXIT",4,,EXIT + POPRSP %esi // pop return stack into %esi + NEXT + +/* + EXIT gets the old %esi which we saved from before on the return stack, and puts it in %esi. + So after this (but just before NEXT) we get: + + QUADRUPLE + +------------------+ + | codeword | + +------------------+ DOUBLE + | addr of DOUBLE ---------------> +------------------+ + +------------------+ | codeword | + %esi -> | addr of DOUBLE | +------------------+ + +------------------+ | addr of DUP | + | addr of EXIT | +------------------+ + +------------------+ | addr of + | + +------------------+ + | addr of EXIT | + +------------------+ + + And NEXT just completes the job by, well, in this case just by calling DOUBLE again :-) + + LITERALS ---------------------------------------------------------------------- + + The final point I "glossed over" before was how to deal with functions that do anything + apart from calling other functions. For example, suppose that DOUBLE was defined like this: + + : DOUBLE 2 * ; + + It does the same thing, but how do we compile it since it contains the literal 2? One way + would be to have a function called "2" (which you'd have to write in assembler), but you'd need + a function for every single literal that you wanted to use. + + FORTH solves this by compiling the function using a special word called LIT: + + +---------------------------+-------+-------+-------+-------+-------+ + | (usual header of DOUBLE) | DOCOL | LIT | 2 | * | EXIT | + +---------------------------+-------+-------+-------+-------+-------+ + + LIT is executed in the normal way, but what it does next is definitely not normal. It + looks at %esi (which now points to the number 2), grabs it, pushes it on the stack, then + manipulates %esi in order to skip the number as if it had never been there. + + What's neat is that the whole grab/manipulate can be done using a single byte single + i386 instruction, our old friend LODSL. Rather than me drawing more ASCII-art diagrams, + see if you can find out how LIT works: +*/ + + defcode "LIT",3,,LIT + // %esi points to the next command, but in this case it points to the next + // literal 32 bit integer. Get that literal into %eax and increment %esi. + // On x86, it's a convenient single byte instruction! (cf. NEXT macro) + lodsl + push %eax // push the literal number on to stack + NEXT + +/* + MEMORY ---------------------------------------------------------------------- + + An important point about FORTH is that it gives you direct access to the lowest levels + of the machine. Manipulating memory directly is done frequently in FORTH, and these are + the primitive words for doing it. +*/ + + defcode "!",1,,STORE + pop %ebx // address to store at + pop %eax // data to store there + mov %eax,(%ebx) // store it + NEXT + + defcode "@",1,,FETCH + pop %ebx // address to fetch + mov (%ebx),%eax // fetch it + push %eax // push value onto stack + NEXT + + defcode "+!",2,,ADDSTORE + pop %ebx // address + pop %eax // the amount to add + addl %eax,(%ebx) // add it + NEXT + + defcode "-!",2,,SUBSTORE + pop %ebx // address + pop %eax // the amount to subtract + subl %eax,(%ebx) // add it + NEXT + +/* + ! and @ (STORE and FETCH) store 32-bit words. It's also useful to be able to read and write bytes + so we also define standard words C@ and C!. + + Byte-oriented operations only work on architectures which permit them (i386 is one of those). + */ + + defcode "C!",2,,STOREBYTE + pop %ebx // address to store at + pop %eax // data to store there + movb %al,(%ebx) // store it + NEXT + + defcode "C@",2,,FETCHBYTE + pop %ebx // address to fetch + xor %eax,%eax + movb (%ebx),%al // fetch it + push %eax // push value onto stack + NEXT + +/* C@C! is a useful byte copy primitive. */ + defcode "C@C!",4,,CCOPY + movl 4(%esp),%ebx // source address + movb (%ebx),%al // get source character + pop %edi // destination address + stosb // copy to destination + push %edi // increment destination address + incl 4(%esp) // increment source address + NEXT + +/* and CMOVE is a block copy operation. */ + defcode "CMOVE",5,,CMOVE + mov %esi,%edx // preserve %esi + pop %ecx // length + pop %edi // destination address + pop %esi // source address + rep movsb // copy source to destination + mov %edx,%esi // restore %esi + NEXT + +/* + BUILT-IN VARIABLES ---------------------------------------------------------------------- + + These are some built-in variables and related standard FORTH words. Of these, the only one that we + have discussed so far was LATEST, which points to the last (most recently defined) word in the + FORTH dictionary. LATEST is also a FORTH word which pushes the address of LATEST (the variable) + on to the stack, so you can read or write it using @ and ! operators. For example, to print + the current value of LATEST (and this can apply to any FORTH variable) you would do: + + LATEST @ . CR + + To make defining variables shorter, I'm using a macro called defvar, similar to defword and + defcode above. (In fact the defvar macro uses defcode to do the dictionary header). +*/ + + .macro defvar name, namelen, flags=0, label, initial=0 + defcode \name,\namelen,\flags,\label + push $var_\name + NEXT + .data + .align 4 +var_\name : + .int \initial + .endm + +/* + The built-in variables are: + + STATE Is the interpreter executing code (0) or compiling a word (non-zero)? + LATEST Points to the latest (most recently defined) word in the dictionary. + HERE Points to the next free byte of memory. When compiling, compiled words go here. + S0 Stores the address of the top of the parameter stack. + BASE The current base for printing and reading numbers. + +*/ + defvar "STATE",5,,STATE + defvar "HERE",4,,HERE + defvar "LATEST",6,,LATEST,name_SYSCALL0 // SYSCALL0 must be last in built-in dictionary + defvar "S0",2,,SZ + defvar "BASE",4,,BASE,10 + +/* + BUILT-IN CONSTANTS ---------------------------------------------------------------------- + + It's also useful to expose a few constants to FORTH. When the word is executed it pushes a + constant value on the stack. + + The built-in constants are: + + VERSION Is the current version of this FORTH. + R0 The address of the top of the return stack. + DOCOL Pointer to DOCOL. + F_IMMED The IMMEDIATE flag's actual value. + F_HIDDEN The HIDDEN flag's actual value. + F_LENMASK The length mask in the flags/len byte. + + SYS_* and the numeric codes of various Linux syscalls (from ) +*/ + +//#include // you might need this instead +#include + + .macro defconst name, namelen, flags=0, label, value + defcode \name,\namelen,\flags,\label + push $\value + NEXT + .endm + + defconst "VERSION",7,,VERSION,JONES_VERSION + defconst "R0",2,,RZ,return_stack_top + defconst "DOCOL",5,,__DOCOL,DOCOL + defconst "F_IMMED",7,,__F_IMMED,F_IMMED + defconst "F_HIDDEN",8,,__F_HIDDEN,F_HIDDEN + defconst "F_LENMASK",9,,__F_LENMASK,F_LENMASK + + defconst "SYS_EXIT",8,,SYS_EXIT,__NR_exit + defconst "SYS_OPEN",8,,SYS_OPEN,__NR_open + defconst "SYS_CLOSE",9,,SYS_CLOSE,__NR_close + defconst "SYS_READ",8,,SYS_READ,__NR_read + defconst "SYS_WRITE",9,,SYS_WRITE,__NR_write + defconst "SYS_CREAT",9,,SYS_CREAT,__NR_creat + defconst "SYS_BRK",7,,SYS_BRK,__NR_brk + + defconst "O_RDONLY",8,,__O_RDONLY,0 + defconst "O_WRONLY",8,,__O_WRONLY,1 + defconst "O_RDWR",6,,__O_RDWR,2 + defconst "O_CREAT",7,,__O_CREAT,0100 + defconst "O_EXCL",6,,__O_EXCL,0200 + defconst "O_TRUNC",7,,__O_TRUNC,01000 + defconst "O_APPEND",8,,__O_APPEND,02000 + defconst "O_NONBLOCK",10,,__O_NONBLOCK,04000 + +/* + RETURN STACK ---------------------------------------------------------------------- + + These words allow you to access the return stack. Recall that the register %ebp always points to + the top of the return stack. +*/ + + defcode ">R",2,,TOR + pop %eax // pop parameter stack into %eax + PUSHRSP %eax // push it on to the return stack + NEXT + + defcode "R>",2,,FROMR + POPRSP %eax // pop return stack on to %eax + push %eax // and push on to parameter stack + NEXT + + defcode "RSP@",4,,RSPFETCH + push %ebp + NEXT + + defcode "RSP!",4,,RSPSTORE + pop %ebp + NEXT + + defcode "RDROP",5,,RDROP + addl $4,%ebp // pop return stack and throw away + NEXT + +/* + PARAMETER (DATA) STACK ---------------------------------------------------------------------- + + These functions allow you to manipulate the parameter stack. Recall that Linux sets up the parameter + stack for us, and it is accessed through %esp. +*/ + + defcode "DSP@",4,,DSPFETCH + mov %esp,%eax + push %eax + NEXT + + defcode "DSP!",4,,DSPSTORE + pop %esp + NEXT + +/* + INPUT AND OUTPUT ---------------------------------------------------------------------- + + These are our first really meaty/complicated FORTH primitives. I have chosen to write them in + assembler, but surprisingly in "real" FORTH implementations these are often written in terms + of more fundamental FORTH primitives. I chose to avoid that because I think that just obscures + the implementation. After all, you may not understand assembler but you can just think of it + as an opaque block of code that does what it says. + + Let's discuss input first. + + The FORTH word KEY reads the next byte from stdin (and pushes it on the parameter stack). + So if KEY is called and someone hits the space key, then the number 32 (ASCII code of space) + is pushed on the stack. + + In FORTH there is no distinction between reading code and reading input. We might be reading + and compiling code, we might be reading words to execute, we might be asking for the user + to type their name -- ultimately it all comes in through KEY. + + The implementation of KEY uses an input buffer of a certain size (defined at the end of this + file). It calls the Linux read(2) system call to fill this buffer and tracks its position + in the buffer using a couple of variables, and if it runs out of input buffer then it refills + it automatically. The other thing that KEY does is if it detects that stdin has closed, it + exits the program, which is why when you hit ^D the FORTH system cleanly exits. + + buffer bufftop + | | + V V + +-------------------------------+--------------------------------------+ + | INPUT READ FROM STDIN ....... | unused part of the buffer | + +-------------------------------+--------------------------------------+ + ^ + | + currkey (next character to read) + + <---------------------- BUFFER_SIZE (4096 bytes) ----------------------> +*/ + + defcode "KEY",3,,KEY + call _KEY + push %eax // push return value on stack + NEXT +_KEY: + mov (currkey),%ebx + cmp (bufftop),%ebx + jge 1f // exhausted the input buffer? + xor %eax,%eax + mov (%ebx),%al // get next key from input buffer + inc %ebx + mov %ebx,(currkey) // increment currkey + ret + +1: // Out of input; use read(2) to fetch more input from stdin. + xor %ebx,%ebx // 1st param: stdin + mov $buffer,%ecx // 2nd param: buffer + mov %ecx,currkey + mov $BUFFER_SIZE,%edx // 3rd param: max length + mov $__NR_read,%eax // syscall: read + int $0x80 + test %eax,%eax // If %eax <= 0, then exit. + jbe 2f + addl %eax,%ecx // buffer+%eax = bufftop + mov %ecx,bufftop + jmp _KEY + +2: // Error or end of input: exit the program. + xor %ebx,%ebx + mov $__NR_exit,%eax // syscall: exit + int $0x80 + + .data + .align 4 +currkey: + .int buffer // Current place in input buffer (next character to read). +bufftop: + .int buffer // Last valid data in input buffer + 1. + +/* + By contrast, output is much simpler. The FORTH word EMIT writes out a single byte to stdout. + This implementation just uses the write system call. No attempt is made to buffer output, but + it would be a good exercise to add it. +*/ + + defcode "EMIT",4,,EMIT + pop %eax + call _EMIT + NEXT +_EMIT: + mov $1,%ebx // 1st param: stdout + + // write needs the address of the byte to write + mov %al,emit_scratch + mov $emit_scratch,%ecx // 2nd param: address + + mov $1,%edx // 3rd param: nbytes = 1 + + mov $__NR_write,%eax // write syscall + int $0x80 + ret + + .data // NB: easier to fit in the .data section +emit_scratch: + .space 1 // scratch used by EMIT + +/* + Back to input, WORD is a FORTH word which reads the next full word of input. + + What it does in detail is that it first skips any blanks (spaces, tabs, newlines and so on). + Then it calls KEY to read characters into an internal buffer until it hits a blank. Then it + calculates the length of the word it read and returns the address and the length as + two words on the stack (with the length at the top of stack). + + Notice that WORD has a single internal buffer which it overwrites each time (rather like + a static C string). Also notice that WORD's internal buffer is just 32 bytes long and + there is NO checking for overflow. 31 bytes happens to be the maximum length of a + FORTH word that we support, and that is what WORD is used for: to read FORTH words when + we are compiling and executing code. The returned strings are not NUL-terminated. + + Start address+length is the normal way to represent strings in FORTH (not ending in an + ASCII NUL character as in C), and so FORTH strings can contain any character including NULs + and can be any length. + + WORD is not suitable for just reading strings (eg. user input) because of all the above + peculiarities and limitations. + + Note that when executing, you'll see: + WORD FOO + which puts "FOO" and length 3 on the stack, but when compiling: + : BAR WORD FOO ; + is an error (or at least it doesn't do what you might expect). Later we'll talk about compiling + and immediate mode, and you'll understand why. +*/ + + defcode "WORD",4,,WORD + call _WORD + push %edi // push base address + push %ecx // push length + NEXT + +_WORD: + /* Search for first non-blank character. Also skip \ comments. */ +1: + call _KEY // get next key, returned in %eax + cmpb $'\\',%al // start of a comment? + je 3f // if so, skip the comment + cmpb $' ',%al + jbe 1b // if so, keep looking + + /* Search for the end of the word, storing chars as we go. */ + mov $word_buffer,%edi // pointer to return buffer +2: + stosb // add character to return buffer + call _KEY // get next key, returned in %al + cmpb $' ',%al // is blank? + ja 2b // if not, keep looping + + /* Return the word (well, the static buffer) and length. */ + sub $word_buffer,%edi + mov %edi,%ecx // return length of the word + mov $word_buffer,%edi // return address of the word + ret + + /* Code to skip \ comments to end of the current line. */ +3: + call _KEY + cmpb $'\n',%al // end of line yet? + jne 3b + jmp 1b + + .data // NB: easier to fit in the .data section + // A static buffer where WORD returns. Subsequent calls + // overwrite this buffer. Maximum word length is 32 chars. +word_buffer: + .space 32 + +/* + As well as reading in words we'll need to read in numbers and for that we are using a function + called NUMBER. This parses a numeric string such as one returned by WORD and pushes the + number on the parameter stack. + + The function uses the variable BASE as the base (radix) for conversion, so for example if + BASE is 2 then we expect a binary number. Normally BASE is 10. + + If the word starts with a '-' character then the returned value is negative. + + If the string can't be parsed as a number (or contains characters outside the current BASE) + then we need to return an error indication. So NUMBER actually returns two items on the stack. + At the top of stack we return the number of unconverted characters (ie. if 0 then all characters + were converted, so there is no error). Second from top of stack is the parsed number or a + partial value if there was an error. +*/ + defcode "NUMBER",6,,NUMBER + pop %ecx // length of string + pop %edi // start address of string + call _NUMBER + push %eax // parsed number + push %ecx // number of unparsed characters (0 = no error) + NEXT + +_NUMBER: + xor %eax,%eax + xor %ebx,%ebx + + test %ecx,%ecx // trying to parse a zero-length string is an error, but will return 0. + jz 5f + + movl var_BASE,%edx // get BASE (in %dl) + + // Check if first character is '-'. + movb (%edi),%bl // %bl = first character in string + inc %edi + push %eax // push 0 on stack + cmpb $'-',%bl // negative number? + jnz 2f + pop %eax + push %ebx // push <> 0 on stack, indicating negative + dec %ecx + jnz 1f + pop %ebx // error: string is only '-'. + movl $1,%ecx + ret + + // Loop reading digits. +1: imull %edx,%eax // %eax *= BASE + movb (%edi),%bl // %bl = next character in string + inc %edi + + // Convert 0-9, A-Z to a number 0-35. +2: subb $'0',%bl // < '0'? + jb 4f + cmp $10,%bl // <= '9'? + jb 3f + subb $17,%bl // < 'A'? (17 is 'A'-'0') + jb 4f + addb $10,%bl + +3: cmp %dl,%bl // >= BASE? + jge 4f + + // OK, so add it to %eax and loop. + add %ebx,%eax + dec %ecx + jnz 1b + + // Negate the result if first character was '-' (saved on the stack). +4: pop %ebx + test %ebx,%ebx + jz 5f + neg %eax + +5: ret + +/* + DICTIONARY LOOK UPS ---------------------------------------------------------------------- + + We're building up to our prelude on how FORTH code is compiled, but first we need yet more infrastructure. + + The FORTH word FIND takes a string (a word as parsed by WORD -- see above) and looks it up in the + dictionary. What it actually returns is the address of the dictionary header, if it finds it, + or 0 if it didn't. + + So if DOUBLE is defined in the dictionary, then WORD DOUBLE FIND returns the following pointer: + + pointer to this + | + | + V + +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+ + | LINK | 6 | D | O | U | B | L | E | 0 | DOCOL | DUP | + | EXIT | + +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+ + + See also >CFA and >DFA. + + FIND doesn't find dictionary entries which are flagged as HIDDEN. See below for why. +*/ + + defcode "FIND",4,,FIND + pop %ecx // %ecx = length + pop %edi // %edi = address + call _FIND + push %eax // %eax = address of dictionary entry (or NULL) + NEXT + +_FIND: + push %esi // Save %esi so we can use it in string comparison. + + // Now we start searching backwards through the dictionary for this word. + mov var_LATEST,%edx // LATEST points to name header of the latest word in the dictionary +1: test %edx,%edx // NULL pointer? (end of the linked list) + je 4f + + // Compare the length expected and the length of the word. + // Note that if the F_HIDDEN flag is set on the word, then by a bit of trickery + // this won't pick the word (the length will appear to be wrong). + xor %eax,%eax + movb 4(%edx),%al // %al = flags+length field + andb $(F_HIDDEN|F_LENMASK),%al // %al = name length + cmpb %cl,%al // Length is the same? + jne 2f + + // Compare the strings in detail. + push %ecx // Save the length + push %edi // Save the address (repe cmpsb will move this pointer) + lea 5(%edx),%esi // Dictionary string we are checking against. + repe cmpsb // Compare the strings. + pop %edi + pop %ecx + jne 2f // Not the same. + + // The strings are the same - return the header pointer in %eax + pop %esi + mov %edx,%eax + ret + +2: mov (%edx),%edx // Move back through the link field to the previous word + jmp 1b // .. and loop. + +4: // Not found. + pop %esi + xor %eax,%eax // Return zero to indicate not found. + ret + +/* + FIND returns the dictionary pointer, but when compiling we need the codeword pointer (recall + that FORTH definitions are compiled into lists of codeword pointers). The standard FORTH + word >CFA turns a dictionary pointer into a codeword pointer. + + The example below shows the result of: + + WORD DOUBLE FIND >CFA + + FIND returns a pointer to this + | >CFA converts it to a pointer to this + | | + V V + +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+ + | LINK | 6 | D | O | U | B | L | E | 0 | DOCOL | DUP | + | EXIT | + +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+ + codeword + + Notes: + + Because names vary in length, this isn't just a simple increment. + + In this FORTH you cannot easily turn a codeword pointer back into a dictionary entry pointer, but + that is not true in most FORTH implementations where they store a back pointer in the definition + (with an obvious memory/complexity cost). The reason they do this is that it is useful to be + able to go backwards (codeword -> dictionary entry) in order to decompile FORTH definitions + quickly. + + What does CFA stand for? My best guess is "Code Field Address". +*/ + + defcode ">CFA",4,,TCFA + pop %edi + call _TCFA + push %edi + NEXT +_TCFA: + xor %eax,%eax + add $4,%edi // Skip link pointer. + movb (%edi),%al // Load flags+len into %al. + inc %edi // Skip flags+len byte. + andb $F_LENMASK,%al // Just the length, not the flags. + add %eax,%edi // Skip the name. + addl $3,%edi // The codeword is 4-byte aligned. + andl $~3,%edi + ret + +/* + Related to >CFA is >DFA which takes a dictionary entry address as returned by FIND and + returns a pointer to the first data field. + + FIND returns a pointer to this + | >CFA converts it to a pointer to this + | | + | | >DFA converts it to a pointer to this + | | | + V V V + +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+ + | LINK | 6 | D | O | U | B | L | E | 0 | DOCOL | DUP | + | EXIT | + +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+ + codeword + + (Note to those following the source of FIG-FORTH / ciforth: My >DFA definition is + different from theirs, because they have an extra indirection). + + You can see that >DFA is easily defined in FORTH just by adding 4 to the result of >CFA. +*/ + + defword ">DFA",4,,TDFA + .int TCFA // >CFA (get code field address) + .int INCR4 // 4+ (add 4 to it to get to next word) + .int EXIT // EXIT (return from FORTH word) + +/* + COMPILING ---------------------------------------------------------------------- + + Now we'll talk about how FORTH compiles words. Recall that a word definition looks like this: + + : DOUBLE DUP + ; + + and we have to turn this into: + + pointer to previous word + ^ + | + +--|------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+ + | LINK | 6 | D | O | U | B | L | E | 0 | DOCOL | DUP | + | EXIT | + +---------+---+---+---+---+---+---+---+---+------------+--|---------+------------+------------+ + ^ len pad codeword | + | V + LATEST points here points to codeword of DUP + + There are several problems to solve. Where to put the new word? How do we read words? How + do we define the words : (COLON) and ; (SEMICOLON)? + + FORTH solves this rather elegantly and as you might expect in a very low-level way which + allows you to change how the compiler works on your own code. + + FORTH has an INTERPRET function (a true interpreter this time, not DOCOL) which runs in a + loop, reading words (using WORD), looking them up (using FIND), turning them into codeword + pointers (using >CFA) and deciding what to do with them. + + What it does depends on the mode of the interpreter (in variable STATE). + + When STATE is zero, the interpreter just runs each word as it looks them up. This is known as + immediate mode. + + The interesting stuff happens when STATE is non-zero -- compiling mode. In this mode the + interpreter appends the codeword pointer to user memory (the HERE variable points to the next + free byte of user memory -- see DATA SEGMENT section below). + + So you may be able to see how we could define : (COLON). The general plan is: + + (1) Use WORD to read the name of the function being defined. + + (2) Construct the dictionary entry -- just the header part -- in user memory: + + pointer to previous word (from LATEST) +-- Afterwards, HERE points here, where + ^ | the interpreter will start appending + | V codewords. + +--|------+---+---+---+---+---+---+---+---+------------+ + | LINK | 6 | D | O | U | B | L | E | 0 | DOCOL | + +---------+---+---+---+---+---+---+---+---+------------+ + len pad codeword + + (3) Set LATEST to point to the newly defined word, ... + + (4) .. and most importantly leave HERE pointing just after the new codeword. This is where + the interpreter will append codewords. + + (5) Set STATE to 1. This goes into compile mode so the interpreter starts appending codewords to + our partially-formed header. + + After : has run, our input is here: + + : DOUBLE DUP + ; + ^ + | + Next byte returned by KEY will be the 'D' character of DUP + + so the interpreter (now it's in compile mode, so I guess it's really the compiler) reads "DUP", + looks it up in the dictionary, gets its codeword pointer, and appends it: + + +-- HERE updated to point here. + | + V + +---------+---+---+---+---+---+---+---+---+------------+------------+ + | LINK | 6 | D | O | U | B | L | E | 0 | DOCOL | DUP | + +---------+---+---+---+---+---+---+---+---+------------+------------+ + len pad codeword + + Next we read +, get the codeword pointer, and append it: + + +-- HERE updated to point here. + | + V + +---------+---+---+---+---+---+---+---+---+------------+------------+------------+ + | LINK | 6 | D | O | U | B | L | E | 0 | DOCOL | DUP | + | + +---------+---+---+---+---+---+---+---+---+------------+------------+------------+ + len pad codeword + + The issue is what happens next. Obviously what we _don't_ want to happen is that we + read ";" and compile it and go on compiling everything afterwards. + + At this point, FORTH uses a trick. Remember the length byte in the dictionary definition + isn't just a plain length byte, but can also contain flags. One flag is called the + IMMEDIATE flag (F_IMMED in this code). If a word in the dictionary is flagged as + IMMEDIATE then the interpreter runs it immediately _even if it's in compile mode_. + + This is how the word ; (SEMICOLON) works -- as a word flagged in the dictionary as IMMEDIATE. + + And all it does is append the codeword for EXIT on to the current definition and switch + back to immediate mode (set STATE back to 0). Shortly we'll see the actual definition + of ; and we'll see that it's really a very simple definition, declared IMMEDIATE. + + After the interpreter reads ; and executes it 'immediately', we get this: + + +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+ + | LINK | 6 | D | O | U | B | L | E | 0 | DOCOL | DUP | + | EXIT | + +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+ + len pad codeword ^ + | + HERE + STATE is set to 0. + + And that's it, job done, our new definition is compiled, and we're back in immediate mode + just reading and executing words, perhaps including a call to test our new word DOUBLE. + + The only last wrinkle in this is that while our word was being compiled, it was in a + half-finished state. We certainly wouldn't want DOUBLE to be called somehow during + this time. There are several ways to stop this from happening, but in FORTH what we + do is flag the word with the HIDDEN flag (F_HIDDEN in this code) just while it is + being compiled. This prevents FIND from finding it, and thus in theory stops any + chance of it being called. + + The above explains how compiling, : (COLON) and ; (SEMICOLON) works and in a moment I'm + going to define them. The : (COLON) function can be made a little bit more general by writing + it in two parts. The first part, called CREATE, makes just the header: + + +-- Afterwards, HERE points here. + | + V + +---------+---+---+---+---+---+---+---+---+ + | LINK | 6 | D | O | U | B | L | E | 0 | + +---------+---+---+---+---+---+---+---+---+ + len pad + + and the second part, the actual definition of : (COLON), calls CREATE and appends the + DOCOL codeword, so leaving: + + +-- Afterwards, HERE points here. + | + V + +---------+---+---+---+---+---+---+---+---+------------+ + | LINK | 6 | D | O | U | B | L | E | 0 | DOCOL | + +---------+---+---+---+---+---+---+---+---+------------+ + len pad codeword + + CREATE is a standard FORTH word and the advantage of this split is that we can reuse it to + create other types of words (not just ones which contain code, but words which contain variables, + constants and other data). +*/ + + defcode "CREATE",6,,CREATE + + // Get the name length and address. + pop %ecx // %ecx = length + pop %ebx // %ebx = address of name + + // Link pointer. + movl var_HERE,%edi // %edi is the address of the header + movl var_LATEST,%eax // Get link pointer + stosl // and store it in the header. + + // Length byte and the word itself. + mov %cl,%al // Get the length. + stosb // Store the length/flags byte. + push %esi + mov %ebx,%esi // %esi = word + rep movsb // Copy the word + pop %esi + addl $3,%edi // Align to next 4 byte boundary. + andl $~3,%edi + + // Update LATEST and HERE. + movl var_HERE,%eax + movl %eax,var_LATEST + movl %edi,var_HERE + NEXT + +/* + Because I want to define : (COLON) in FORTH, not assembler, we need a few more FORTH words + to use. + + The first is , (COMMA) which is a standard FORTH word which appends a 32 bit integer to the user + memory pointed to by HERE, and adds 4 to HERE. So the action of , (COMMA) is: + + previous value of HERE + | + V + +---------+---+---+---+---+---+---+---+---+-- - - - - --+------------+ + | LINK | 6 | D | O | U | B | L | E | 0 | | | + +---------+---+---+---+---+---+---+---+---+-- - - - - --+------------+ + len pad ^ + | + new value of HERE + + and is whatever 32 bit integer was at the top of the stack. + + , (COMMA) is quite a fundamental operation when compiling. It is used to append codewords + to the current word that is being compiled. +*/ + + defcode ",",1,,COMMA + pop %eax // Code pointer to store. + call _COMMA + NEXT +_COMMA: + movl var_HERE,%edi // HERE + stosl // Store it. + movl %edi,var_HERE // Update HERE (incremented) + ret + +/* + Our definitions of : (COLON) and ; (SEMICOLON) will need to switch to and from compile mode. + + Immediate mode vs. compile mode is stored in the global variable STATE, and by updating this + variable we can switch between the two modes. + + For various reasons which may become apparent later, FORTH defines two standard words called + [ and ] (LBRAC and RBRAC) which switch between modes: + + Word Assembler Action Effect + [ LBRAC STATE := 0 Switch to immediate mode. + ] RBRAC STATE := 1 Switch to compile mode. + + [ (LBRAC) is an IMMEDIATE word. The reason is as follows: If we are in compile mode and the + interpreter saw [ then it would compile it rather than running it. We would never be able to + switch back to immediate mode! So we flag the word as IMMEDIATE so that even in compile mode + the word runs immediately, switching us back to immediate mode. +*/ + + defcode "[",1,F_IMMED,LBRAC + xor %eax,%eax + movl %eax,var_STATE // Set STATE to 0. + NEXT + + defcode "]",1,,RBRAC + movl $1,var_STATE // Set STATE to 1. + NEXT + +/* + Now we can define : (COLON) using CREATE. It just calls CREATE, appends DOCOL (the codeword), sets + the word HIDDEN and goes into compile mode. +*/ + + defword ":",1,,COLON + .int WORD // Get the name of the new word + .int CREATE // CREATE the dictionary entry / header + .int LIT, DOCOL, COMMA // Append DOCOL (the codeword). + .int LATEST, FETCH, HIDDEN // Make the word hidden (see below for definition). + .int RBRAC // Go into compile mode. + .int EXIT // Return from the function. + +/* + ; (SEMICOLON) is also elegantly simple. Notice the F_IMMED flag. +*/ + + defword ";",1,F_IMMED,SEMICOLON + .int LIT, EXIT, COMMA // Append EXIT (so the word will return). + .int LATEST, FETCH, HIDDEN // Toggle hidden flag -- unhide the word (see below for definition). + .int LBRAC // Go back to IMMEDIATE mode. + .int EXIT // Return from the function. + +/* + EXTENDING THE COMPILER ---------------------------------------------------------------------- + + Words flagged with IMMEDIATE (F_IMMED) aren't just for the FORTH compiler to use. You can define + your own IMMEDIATE words too, and this is a crucial aspect when extending basic FORTH, because + it allows you in effect to extend the compiler itself. Does gcc let you do that? + + Standard FORTH words like IF, WHILE, ." and so on are all written as extensions to the basic + compiler, and are all IMMEDIATE words. + + The IMMEDIATE word toggles the F_IMMED (IMMEDIATE flag) on the most recently defined word, + or on the current word if you call it in the middle of a definition. + + Typical usage is: + + : MYIMMEDWORD IMMEDIATE + ...definition... + ; + + but some FORTH programmers write this instead: + + : MYIMMEDWORD + ...definition... + ; IMMEDIATE + + The two usages are equivalent, to a first approximation. +*/ + + defcode "IMMEDIATE",9,F_IMMED,IMMEDIATE + movl var_LATEST,%edi // LATEST word. + addl $4,%edi // Point to name/flags byte. + xorb $F_IMMED,(%edi) // Toggle the IMMED bit. + NEXT + +/* + 'addr HIDDEN' toggles the hidden flag (F_HIDDEN) of the word defined at addr. To hide the + most recently defined word (used above in : and ; definitions) you would do: + + LATEST @ HIDDEN + + 'HIDE word' toggles the flag on a named 'word'. + + Setting this flag stops the word from being found by FIND, and so can be used to make 'private' + words. For example, to break up a large word into smaller parts you might do: + + : SUB1 ... subword ... ; + : SUB2 ... subword ... ; + : SUB3 ... subword ... ; + : MAIN ... defined in terms of SUB1, SUB2, SUB3 ... ; + HIDE SUB1 + HIDE SUB2 + HIDE SUB3 + + After this, only MAIN is 'exported' or seen by the rest of the program. +*/ + + defcode "HIDDEN",6,,HIDDEN + pop %edi // Dictionary entry. + addl $4,%edi // Point to name/flags byte. + xorb $F_HIDDEN,(%edi) // Toggle the HIDDEN bit. + NEXT + + defword "HIDE",4,,HIDE + .int WORD // Get the word (after HIDE). + .int FIND // Look up in the dictionary. + .int HIDDEN // Set F_HIDDEN flag. + .int EXIT // Return. + +/* + ' (TICK) is a standard FORTH word which returns the codeword pointer of the next word. + + The common usage is: + + ' FOO , + + which appends the codeword of FOO to the current word we are defining (this only works in compiled code). + + You tend to use ' in IMMEDIATE words. For example an alternate (and rather useless) way to define + a literal 2 might be: + + : LIT2 IMMEDIATE + ' LIT , \ Appends LIT to the currently-being-defined word + 2 , \ Appends the number 2 to the currently-being-defined word + ; + + So you could do: + + : DOUBLE LIT2 * ; + + (If you don't understand how LIT2 works, then you should review the material about compiling words + and immediate mode). + + This definition of ' uses a cheat which I copied from buzzard92. As a result it only works in + compiled code. It is possible to write a version of ' based on WORD, FIND, >CFA which works in + immediate mode too. +*/ + defcode "'",1,,TICK + lodsl // Get the address of the next word and skip it. + pushl %eax // Push it on the stack. + NEXT + +/* + BRANCHING ---------------------------------------------------------------------- + + It turns out that all you need in order to define looping constructs, IF-statements, etc. + are two primitives. + + BRANCH is an unconditional branch. 0BRANCH is a conditional branch (it only branches if the + top of stack is zero). + + The diagram below shows how BRANCH works in some imaginary compiled word. When BRANCH executes, + %esi starts by pointing to the offset field (compare to LIT above): + + +---------------------+-------+---- - - ---+------------+------------+---- - - - ----+------------+ + | (Dictionary header) | DOCOL | | BRANCH | offset | (skipped) | word | + +---------------------+-------+---- - - ---+------------+-----|------+---- - - - ----+------------+ + ^ | ^ + | | | + | +-----------------------+ + %esi added to offset + + The offset is added to %esi to make the new %esi, and the result is that when NEXT runs, execution + continues at the branch target. Negative offsets work as expected. + + 0BRANCH is the same except the branch happens conditionally. + + Now standard FORTH words such as IF, THEN, ELSE, WHILE, REPEAT, etc. can be implemented entirely + in FORTH. They are IMMEDIATE words which append various combinations of BRANCH or 0BRANCH + into the word currently being compiled. + + As an example, code written like this: + + condition-code IF true-part THEN rest-code + + compiles to: + + condition-code 0BRANCH OFFSET true-part rest-code + | ^ + | | + +-------------+ +*/ + + defcode "BRANCH",6,,BRANCH + add (%esi),%esi // add the offset to the instruction pointer + NEXT + + defcode "0BRANCH",7,,ZBRANCH + pop %eax + test %eax,%eax // top of stack is zero? + jz code_BRANCH // if so, jump back to the branch function above + lodsl // otherwise we need to skip the offset + NEXT + +/* + LITERAL STRINGS ---------------------------------------------------------------------- + + LITSTRING is a primitive used to implement the ." and S" operators (which are written in + FORTH). See the definition of those operators later. + + TELL just prints a string. It's more efficient to define this in assembly because we + can make it a single Linux syscall. +*/ + + defcode "LITSTRING",9,,LITSTRING + lodsl // get the length of the string + push %esi // push the address of the start of the string + push %eax // push it on the stack + addl %eax,%esi // skip past the string + addl $3,%esi // but round up to next 4 byte boundary + andl $~3,%esi + NEXT + + defcode "TELL",4,,TELL + mov $1,%ebx // 1st param: stdout + pop %edx // 3rd param: length of string + pop %ecx // 2nd param: address of string + mov $__NR_write,%eax // write syscall + int $0x80 + NEXT + +/* + QUIT AND INTERPRET ---------------------------------------------------------------------- + + QUIT is the first FORTH function called, almost immediately after the FORTH system "boots". + As explained before, QUIT doesn't "quit" anything. It does some initialisation (in particular + it clears the return stack) and it calls INTERPRET in a loop to interpret commands. The + reason it is called QUIT is because you can call it from your own FORTH words in order to + "quit" your program and start again at the user prompt. + + INTERPRET is the FORTH interpreter ("toploop", "toplevel" or "REPL" might be a more accurate + description -- see: http://en.wikipedia.org/wiki/REPL). +*/ + + // QUIT must not return (ie. must not call EXIT). + defword "QUIT",4,,QUIT + .int RZ,RSPSTORE // R0 RSP!, clear the return stack + .int INTERPRET // interpret the next word + .int BRANCH,-8 // and loop (indefinitely) + +/* + This interpreter is pretty simple, but remember that in FORTH you can always override + it later with a more powerful one! + */ + defcode "INTERPRET",9,,INTERPRET + call _WORD // Returns %ecx = length, %edi = pointer to word. + + // Is it in the dictionary? + xor %eax,%eax + movl %eax,interpret_is_lit // Not a literal number (not yet anyway ...) + call _FIND // Returns %eax = pointer to header or 0 if not found. + test %eax,%eax // Found? + jz 1f + + // In the dictionary. Is it an IMMEDIATE codeword? + mov %eax,%edi // %edi = dictionary entry + movb 4(%edi),%al // Get name+flags. + push %ax // Just save it for now. + call _TCFA // Convert dictionary entry (in %edi) to codeword pointer. + pop %ax + andb $F_IMMED,%al // Is IMMED flag set? + mov %edi,%eax + jnz 4f // If IMMED, jump straight to executing. + + jmp 2f + +1: // Not in the dictionary (not a word) so assume it's a literal number. + incl interpret_is_lit + call _NUMBER // Returns the parsed number in %eax, %ecx > 0 if error + test %ecx,%ecx + jnz 6f + mov %eax,%ebx + mov $LIT,%eax // The word is LIT + +2: // Are we compiling or executing? + movl var_STATE,%edx + test %edx,%edx + jz 4f // Jump if executing. + + // Compiling - just append the word to the current dictionary definition. + call _COMMA + mov interpret_is_lit,%ecx // Was it a literal? + test %ecx,%ecx + jz 3f + mov %ebx,%eax // Yes, so LIT is followed by a number. + call _COMMA +3: NEXT + +4: // Executing - run it! + mov interpret_is_lit,%ecx // Literal? + test %ecx,%ecx // Literal? + jnz 5f + + // Not a literal, execute it now. This never returns, but the codeword will + // eventually call NEXT which will reenter the loop in QUIT. + jmp *(%eax) + +5: // Executing a literal, which means push it on the stack. + push %ebx + NEXT + +6: // Parse error (not a known word or a number in the current BASE). + // Print an error message followed by up to 40 characters of context. + mov $2,%ebx // 1st param: stderr + mov $errmsg,%ecx // 2nd param: error message + mov $errmsgend-errmsg,%edx // 3rd param: length of string + mov $__NR_write,%eax // write syscall + int $0x80 + + mov (currkey),%ecx // the error occurred just before currkey position + mov %ecx,%edx + sub $buffer,%edx // %edx = currkey - buffer (length in buffer before currkey) + cmp $40,%edx // if > 40, then print only 40 characters + jle 7f + mov $40,%edx +7: sub %edx,%ecx // %ecx = start of area to print, %edx = length + mov $__NR_write,%eax // write syscall + int $0x80 + + mov $errmsgnl,%ecx // newline + mov $1,%edx + mov $__NR_write,%eax // write syscall + int $0x80 + + NEXT + + .section .rodata +errmsg: .ascii "PARSE ERROR: " +errmsgend: +errmsgnl: .ascii "\n" + + .data // NB: easier to fit in the .data section + .align 4 +interpret_is_lit: + .int 0 // Flag used to record if reading a literal + +/* + ODDS AND ENDS ---------------------------------------------------------------------- + + CHAR puts the ASCII code of the first character of the following word on the stack. For example + CHAR A puts 65 on the stack. + + EXECUTE is used to run execution tokens. See the discussion of execution tokens in the + FORTH code for more details. + + SYSCALL0, SYSCALL1, SYSCALL2, SYSCALL3 make a standard Linux system call. (See + for a list of system call numbers). As their name suggests these forms take between 0 and 3 + syscall parameters, plus the system call number. + + In this FORTH, SYSCALL0 must be the last word in the built-in (assembler) dictionary because we + initialise the LATEST variable to point to it. This means that if you want to extend the assembler + part, you must put new words before SYSCALL0, or else change how LATEST is initialised. +*/ + + defcode "CHAR",4,,CHAR + call _WORD // Returns %ecx = length, %edi = pointer to word. + xor %eax,%eax + movb (%edi),%al // Get the first character of the word. + push %eax // Push it onto the stack. + NEXT + + defcode "EXECUTE",7,,EXECUTE + pop %eax // Get xt into %eax + jmp *(%eax) // and jump to it. + // After xt runs its NEXT will continue executing the current word. + + defcode "SYSCALL3",8,,SYSCALL3 + pop %eax // System call number (see ) + pop %ebx // First parameter. + pop %ecx // Second parameter + pop %edx // Third parameter + int $0x80 + push %eax // Result (negative for -errno) + NEXT + + defcode "SYSCALL2",8,,SYSCALL2 + pop %eax // System call number (see ) + pop %ebx // First parameter. + pop %ecx // Second parameter + int $0x80 + push %eax // Result (negative for -errno) + NEXT + + defcode "SYSCALL1",8,,SYSCALL1 + pop %eax // System call number (see ) + pop %ebx // First parameter. + int $0x80 + push %eax // Result (negative for -errno) + NEXT + + defcode "SYSCALL0",8,,SYSCALL0 + pop %eax // System call number (see ) + int $0x80 + push %eax // Result (negative for -errno) + NEXT + +/* + DATA SEGMENT ---------------------------------------------------------------------- + + Here we set up the Linux data segment, used for user definitions and variously known as just + the 'data segment', 'user memory' or 'user definitions area'. It is an area of memory which + grows upwards and stores both newly-defined FORTH words and global variables of various + sorts. + + It is completely analogous to the C heap, except there is no generalised 'malloc' and 'free' + (but as with everything in FORTH, writing such functions would just be a Simple Matter + Of Programming). Instead in normal use the data segment just grows upwards as new FORTH + words are defined/appended to it. + + There are various "features" of the GNU toolchain which make setting up the data segment + more complicated than it really needs to be. One is the GNU linker which inserts a random + "build ID" segment. Another is Address Space Randomization which means we can't tell + where the kernel will choose to place the data segment (or the stack for that matter). + + Therefore writing this set_up_data_segment assembler routine is a little more complicated + than it really needs to be. We ask the Linux kernel where it thinks the data segment starts + using the brk(2) system call, then ask it to reserve some initial space (also using brk(2)). + + You don't need to worry about this code. +*/ + .text + .set INITIAL_DATA_SEGMENT_SIZE,65536 +set_up_data_segment: + xor %ebx,%ebx // Call brk(0) + movl $__NR_brk,%eax + int $0x80 + movl %eax,var_HERE // Initialise HERE to point at beginning of data segment. + addl $INITIAL_DATA_SEGMENT_SIZE,%eax // Reserve nn bytes of memory for initial data segment. + movl %eax,%ebx // Call brk(HERE+INITIAL_DATA_SEGMENT_SIZE) + movl $__NR_brk,%eax + int $0x80 + ret + +/* + We allocate static buffers for the return static and input buffer (used when + reading in files and text that the user types in). +*/ + .set RETURN_STACK_SIZE,8192 + .set BUFFER_SIZE,4096 + + .bss +/* FORTH return stack. */ + .align 4096 +return_stack: + .space RETURN_STACK_SIZE +return_stack_top: // Initial top of return stack. + +/* This is used as a temporary input buffer when reading from files or the terminal. */ + .align 4096 +buffer: + .space BUFFER_SIZE + +/* + START OF FORTH CODE ---------------------------------------------------------------------- + + We've now reached the stage where the FORTH system is running and self-hosting. All further + words can be written as FORTH itself, including words like IF, THEN, .", etc which in most + languages would be considered rather fundamental. + + I used to append this here in the assembly file, but I got sick of fighting against gas's + crack-smoking (lack of) multiline string syntax. So now that is in a separate file called + jonesforth.f + + If you don't already have that file, download it from http://annexia.org/forth in order + to continue the tutorial. +*/ + + +/* END OF jonesforth.S */ diff --git a/test.c b/test.c index 022f828..a011c6c 100644 --- a/test.c +++ b/test.c @@ -20,10 +20,10 @@ void test(void) asm("push %rcx"); asm("push %rdx"); asm("push %rbx"); - asm("push %rsi"); - asm("push %rdi"); asm("push %rsp"); asm("push %rbp"); + asm("push %rsi"); + asm("push %rdi"); asm("push %r8"); asm("push %r9"); asm("push %r10"); @@ -32,4 +32,42 @@ void test(void) asm("push %r13"); asm("push %r14"); asm("push %r15"); + + asm("pop %rax"); + asm("pop %rcx"); + asm("pop %rdx"); + asm("pop %rbx"); + asm("pop %rsp"); + asm("pop %rbp"); + asm("pop %rsi"); + asm("pop %rdi"); + asm("pop %r8"); + asm("pop %r9"); + asm("pop %r10"); + asm("pop %r11"); + asm("pop %r12"); + asm("pop %r13"); + asm("pop %r14"); + asm("pop %r15"); + + + asm("mov $0x2A, %rax"); + asm("mov $0x2A, %rcx"); + asm("mov $0x2A, %rdx"); + asm("mov $0x2A, %rbx"); + asm("mov $0x2A, %rsp"); + asm("mov $0x2A, %rbp"); + asm("mov $0x2A, %rsi"); + asm("mov $0x2A, %rdi"); + asm("mov $0x2A, %r8"); + asm("mov $0x2A, %r9"); + asm("mov $0x2A, %r10"); + asm("mov $0x2A, %r11"); + asm("mov $0x2A, %r12"); + asm("mov $0x2A, %r13"); + asm("mov $0x2A, %r14"); + asm("mov $0x2A, %r15"); + + asm("syscall"); + } -- 2.52.0