1 # NasmJF - a NASM port of JONESFORTH
2
3 This is a fully-functioning Forth interpreter faithfully ported from the original
4 by Richard W.M. Jones:
5
6 <a href="https://rwmj.wordpress.com/2010/08/07/jonesforth-git-repository/">https://rwmj.wordpress.com/2010/08/07/jonesforth-git-repository/"></a>
7
8 You can see the full original source in the `jonesforth/` directory in this repo.
9
10 Assemble and run `nasmjf` like so:
11
12 $ ./build.sh
13 $ ./nasmjf
14 JONESFORTH VERSION 1
15 20643 CELLS REMAINING
16 OK
17 : hello ." Hello world!" CR ;
18 hello
19 Hello world!
20 BYE
21 $
22
23 This repo is a port from the original GNU Assembler (GAS) implementation to
24 the Netwide Assembler (NASM). The biggest difference between the two assemblers
25 is AT&T-style GAS syntax vs. Intel-style NASM syntax. But I have made a couple
26 changes. The biggest one is that `nasmjf` loads the `jonesforth.f` source file
27 (containing the second half of the interpreter written in Forth) upon startup.
28
29 See "Loads Jones's FORTH source on start" below.
30
31
32 ## Current status
33
34 It's done! It passes the original JONESFORTH tests. See
35 `test.sh` in the root of this repo.
36
37
38 ## Why does this exist?
39
40 Check out the `devlog/log*.txt` text files. They're my rambling learning-in-public and
41 thinking "out loud" way of describing what I'm up to. The latest log will probably
42 give an idea of what I'm currently doing or what I've most recently completed.
43
44 I also wrote an article about my delightful process with this project:
45 <a href="http://ratfactor.com/assembly-nights">http://ratfactor.com/assembly-nights</a>
46
47 After completing this project, here's my conclusions:
48 <a href="http://ratfactor.com/nasmjf/done">http://ratfactor.com/nasmjf/done</a>
49
50
51 ## Compiling and running
52
53 You'll need the NASM assembler, a linker such as `ld`, and a Linux computer
54 (JF relies on raw syscalls). And a sense of adventure.
55
56 To build the `nasmjf` executabe, run `build.sh`. (Or see what it does.)
57
58 Manually assemble and link like so:
59
60 $ nasm -f elf32 -g -o nasmjf.o nasmjf.asm
61 $ ld nasmjf.o -o nasmjf
62 $ rm nasmjf.o
63
64 Run by calling the executable you just compiled:
65
66
67 $ ./nasmjf
68 'A' EMIT
69 A
70
71
72 If you're going to use JONESFORTH for anything longer than a simple line or
73 two, I _highly_ recommend wrapping it in `readline` with the excellent `rlwrap`
74 (https://github.com/hanslub42/rlwrap) like so:
75
76 $ rlwrap ./nasmjf
77
78 Then you'll have line editing, history (up arrow lets you re-enter and edit the
79 last line), and even persistent history between Forth sessions!
80
81 ## Loads Jones's FORTH source on start
82
83 The implementation of JONESFORTH is in two parts: an assembly language
84 "bootstrap" and additional essential word definitions written in FORTH.
85
86 This NASM contains a hard-coded path to the `jonesforth.f` FORTH source file
87 and reads it automatically when the interpreter starts. This is to make
88 starting and debugging the system easier and more convenient.
89
90 If you wish to disable or simply examine this change, search for lines with
91 comments containing the string `LOADJF`. You can comment out most of these
92 lines. A few will need to remain. Figuring out which is "left as an exercise
93 for the reader", as they say.
94
95
96 ## GNU Debugger
97
98 I've made heavy use of the GNU Debugger to fix mistakes, understand what
99 my program is doing, and in these early stages, it's nearly the only way
100 to tell what's happening in the program at all.
101
102 I'm assembling with DWARF2 debugging info. See the `r` script for params.
103
104 See `gdb.script` for current defaults I'm using.
105
106 Show stuff:
107
108 maint info sections # memory sections
109 info addr word_buffer # address of symbol (label/var/func)
110 info sym 0x804c608 # reverse of info addr, symbol at addr
111 info var buff # list (with addr!) of symbol names w/ "buff"
112 info var # list ALL symbols
113 info var var_ # list all symbols that start with "var_"
114
115 Print values (register, label, literal numbers (handy as base converter)
116
117 p 0x50 # prints 80
118 p/x 80 # prints 0x50
119 p/x (int)some_label # show 4 bytes (32b) of data at some_label in hex
120 p/x &some_label # ADDRESS of some_label
121
122 Print value at memory location
123
124 x/x &some_label # show a byte of data at some_label in hex
125 x/s &some_label # show a string at some_label
126 x/4x &some_label # show four consecutive bytes
127
128 Set temporary break and jump to location (by label)
129
130 tbreak docol
131 jump docol
132
133 Create GDB commands
134
135 define foo
136 p $arg0
137 p $arg1
138 end
139
140
141 ## GNU Screen
142
143 See the file `screenrc` in this repo to see the current convenience setup.
144 In short, I've got a GDB session and Vim session open in separate windows
145 so I can quickly toggle between them. Anything outside of those two
146 applications is best done in a new window to keep from accidentally closing
147 one of the two main windows.
148
149 * `C-j C-j` toggle between main windows
150 * `C-j c` create a new window with a shell
151 * `C-j H` start (or stop) logging window (not actually what I want)
152 * `C-j h` save hardcopy of scrollback buffer (actually what I want)
153 * `C-j ?` help (show other shortcuts)
154
155 I'm using the hardcopy feature to help me record running each milestone of
156 progress in GDB sessions to test and document (and celebrate!) the work.
157
158 An alias called `jf` starts my two-windowe session like so:
159
160 alias jf='screen -c nasmjf/screenrc'
161
162
163 ## .vimrc
164
165 My whole setup on this machine is dedicated to this project.
166 Here's the entirety of my current `.vimrc`:
167
168 set tabstop=8 softtabstop=0 expandtab shiftwidth=4 smarttab
169 colorscheme elflord
170 " simple buffer switching mappings for a handful of files
171 nnoremap <right> :bn<cr>
172 nnoremap <left> :bp<cr>
173 " my eeepc chugs when trying to apply highlighting to this large asm file
174 au BufRead jonesforth.S set syntax=text nowrap
175 au BufRead nasmjf.listing set nowrap
176 let mapleader = ","
177
178
179 ## PUBLIC DOMAIN
180
181 Because Richard Jones released his work as public domain, it's only right
182 that I should release my port also as public domain. So here's the license:
183
184 I, the copyright holder of this work, hereby release it into the public domain.
185 This applies worldwide.
186
187 In case this is not legally possible, I grant any entity the right to use this
188 work for any purpose, without any conditions, unless such conditions are
189 required by law.