git @ Cat's Eye Technologies SITU-SOL / fd2b754
Import contents of Bootstrap Zero blog during RC 2015/07 Chris Pressey 6 years ago
97 changed file(s) with 635 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
33 SITU-SOL is a programming environment for 6502-based computers that was
44 written by hand during RetroChallenge 07/2015.
55
6 For more information, see the [Bootstrap Zero](http://bootstrap-zero.tumblr.com/)
7 blog (you might want to go to its [archive](http://bootstrap-zero.tumblr.com/archive)
8 and read the posts in chronological order.)
6 For more information, see the posts to the Bootstrap Zero blog, archived
7 in this repo in [doc/bootstrap-zero/README.md](doc/bootstrap-zero/README.md).
8
9 While SITU-SOL is quite generic, an emulated Commodore 64 was used to
10 host it and test it during its development, so many of the instructions
11 below are specific to the C64.
912
1013 Supporting tools
1114 ----------------
1215
13 This repository contains the following supporting tools, written in BASIC:
16 This repository contains the following supporting tools, written in
17 Commodore BASIC 2.0:
1418
1519 * `binloader`, the first version of the simulated bit-entering facility,
1620 used in the warm-up
1721 * `frontpanel`, the improved version of the front-panel simulator,
18 used to enter SITU-MON
22 used to enter SITU-MON. (This tool is also now known as SITU-PAN.)
1923
2024 BASIC sources for these are in `src`; the tokenized PRG files are in `bin`.
2125
3438 * `situ-mon` is a PRG file containing a dump of what memory $8100-$81FF
3539 looked like just after SITU-MON was entered and fixed. You can run
3640 it from BASIC immediate mode like so:
37
41
3842 LOAD "SITU-MON",8,1
3943 SYS 33024
40
44
4145 * `situ-sol` is a PRG file containing a dump of what memory $8100-$8520
4246 looked like just after SITU-SOL was entered and fixed. It also includes
4347 SITU-MON — because SITU-SOL calls routines from it — and 256 bytes of
4448 almost-unused code between $8200 and $82FF.
45
49
4650 It can be started from BASIC immediate mode like so:
47
51
4852 LOAD "SITU-SOL",8,1
4953 POKE 2304,0:SYS 33830
50
54
5155 But! There is no symbal table. (The `POKE 2304,0` is to stop SITU-SOL
5256 from mistakenly behaving as if there's a symbal table at that address,
5357 in case that byte isn't zero.) You may wish to load a symbal table
0 Bootstrap Zero
1 ==============
2
3 _being a record of the posts made to the Bootstrap Zero blog during
4 RetroChallenge 2015/07_
5
6 Write it by hand
7 ----------------
8
9 _May 31, 2015_
10
11 Say you want to write a program. You need to pick a programming language to write it in — BASIC, say.
12
13 Then, to run it, you need a BASIC interpreter. But what if you don't have a BASIC interpreter? Then you need to write one.
14
15 But a BASIC interpreter is a program, too. You need to pick a programming language to write it in — assembly language, say.
16
17 Then, to assemble it, you need an assembler. But what if you don't have an assembler? Then you need to write one.
18
19 But an assembler is a program, too. You need to pick a programming language to write it in.
20
21 You could write it in assembly, or even BASIC; but since you don't have an assembler or a BASIC interpreter yet, you won't be able to run your assembler, and it won't be very useful to you.
22
23 So, what's to be done?
24
25 **Write it by hand**.
26
27 Then convert it to machine code by hand. Then put that machine code into the computer somehow.
28
29 This will be the general theme of [Cat's Eye Technologies](http://catseye.tc/)' project for [RetroChallenge](http://retrochallenge.org/) 2015/07: **assume there is no programming environment available on the machine, write one, convert it to machine code, and enter that machine code -- manually.**
30
31 We're still working out the details, but...
32
33 Lacking appropriate physical hardware to do this on, we'll be using an emulator.
34
35 Being most familiar with 6502 and the Commodore 64 architecture, the emulator will probably be [VICE](http://vice-emu.sourceforge.net/).
36
37 If there was *really* no programming environment *at all* on the machine, the code would need to be entered in a very primitive way -- setting DIP switches, for example. We probably won't go that far. But we will try to come up with something comparably crude for the code-entry part.
38
39 The programming environment might not be BASIC, and it might not be an assembler; it's more likely, in fact, to be something like FORTH.
40
41 (Or, depending on how it goes, it might be something completely different! But it will definitely follow the theme of **writing it by hand**.)
42
43 Why write it by hand?
44 ---------------------
45
46 _June 23, 2015_
47
48 In the previous post, I outlined the project that
49 [Cat's Eye Technologies](http://catseye.tc/) plans to do
50 for [RetroChallenge](http://retrochallenge.org/) 2015/07:
51 writing a programming environment by hand.
52
53 But I didn't go into *why* I chose this project.
54
55 The reasons are fairly simple. In 2015, and in fact for decades now,
56 software for computers has been developed almost exclusively with the aid of computers.
57
58 The sheer pervasiveness of this situation might almost lull you into an impression that it has always been done this way.
59
60 But, even if you don't know the history, you can logically reason that it can't possibly have *always* been done this way; in order to develop software using a computer, there needs to be software *on* that computer first. It's a chicken-and-egg problem.
61
62 The very first computers must have had *no* software on them, and the software for them must have been developed *without* using a computer, and then loaded into the computer... somehow. Only after that point could the computer be used to develop more and newer software for itself.
63
64 This situation, incidentally, explains the name of this blog. Getting over this chicken-and-egg complication is called **bootstrapping**, after the mythical idea that one might reach down and, grabbing hold of one's own boot-straps, lift oneself off the ground. The concept shows up in several places in computer engineering, particularly in compiler development, but even in the common process of powering on a computer: we say the computer "boots", which is just a shortening of "bootstrap".
65
66 Meanwhile, "zero" refers to the fact that there is no software on the computer yet, and suggests an origin point; we are starting with nothing. (OK, even if that's not *absolutely* true, let's say we're trying to get as
67 close to the "zero point of software development" as reasonably possible.)
68
69 Or to put it another way: **pen and paper is also a programming environment**.
70
71 And, since it's *so* much easier to develop software using a computer, it's rather a foreign environment these days. So let's revisit it, lest habituation to screens and keyboards dulls our imagination!
72
73 For the next post, I hope to write a bit about the part where the code is actually loaded into the computer (since that's the part we're going to fudge the most, so I'd like to impart what it's like, the best I can.) And while July is underway, I hope to be able to update the blog regularly with photos of the handwritten materials. Stay tuned!
74
75 Loading the code
76 ----------------
77
78 _June 26, 2015_
79
80 The most “cheating” part of this project will be avoiding the actual loading of the machine code into an actual machine, so I feel that should describe what it would _actually_ be like, in the real world.
81
82 For the sake of example, assume we’ve already written a programming environment — the one that we want to put into our computer, a computer that doesn’t have any sort of programming environment on it yet. Assume we’ve written this program by hand, on paper… and that we’ve already converted it all into machine code. The first line of it might look something like this:
83
84 ![](images/tumblr_inline_npj0dzr5L21tvda25_540.jpg)
85
86 …followed by many, many more lines.
87
88 There are, of course, many ways to get a program into a computer – that is, into its memory.
89
90 In the modern world, we would just open a text editor and start typing in the program. But think of how much hardware and software is required to support this! Decoding the keystrokes from the keyboard is not terribly complicated, but displaying characters on a video display is quite another matter. And never mind that the text editor is yet another program that someone had to write (and get into the computer somehow.)
91
92 I’ll describe a much more primitive method here.
93
94 Glossing over some of the details, a typical memory circuit has a number of **address lines**, a number of **data lines**, and a **read/write gate**. For example, a 64 kilobyte bank of memory might have 16 address lines and 8 data lines.
95
96 To locate a byte in memory, you put a binary-encoded version of its address on the address lines. To read that byte, you set the read/write gate to “read” and look at what value is on the data lines. To write a byte, you instead put the value you write onto the data lines, and set the read/write gate to “write”.
97
98 Normally, the CPU is doing all this memory-access. But all these lines, **they’re just wires with voltages on them**. So you can do all this reading and writing **by hand, using switches**.
99
100 In fact, the front panels of some of the earliest home computers had switches and lights on them for just this purpose, like the Altair 8800 shown here:
101
102 ![](images/tumblr_inline_npj713CSRw1tvda25_540.jpg)
103
104 And in the absence of any other hardware, **this was how you programmed it.** You flipped the switches to represent the binary value you wanted to write into memory, and pressed a button to write it.
105
106 I was going to walk through this process and ask you to imagine it, but [@retrochallenge](https://twitter.com/retrochallenge) pointed out the [1802 Membership Card](http://www.sunrise-ev.com/membershipcard.htm), which is a kit based on the COSMAC ELF, which, like the Altair 8800, was programmed with front panel switches.
107
108 So instead, you can [read the instructions for 1802 Membership Card code loading](http://www.retrotechnology.com/memship/mship_test.html),
109 or watch [this video](https://www.youtube.com/embed/ZgTkOW70MHs?feature=oembed) to see what loading code this way is like.
110
111 And now that I’ve shown you this, there is something I’d like to point out...
112
113 There’s a simple improvement over switches that’s fairly obvious when
114 you think about it a bit. Instead of manually changing the switches with
115 your fingers, why not have some kind of mechanical contrivance which sets the
116 switches according to a pre-arranged pattern?
117
118 Indeed, this technology exists, and you have probably heard of it: the _punched card_.
119
120 ![](images/tumblr_inline_nqi14lL43P1tvda25_540.jpg)
121
122 At its simplest, a punchcard reader is barely any more complex than front-panel switches. When a card is inserted, switch contacts close where there are holes in the card, and stay open where
123 there aren’t holes. And then that bit pattern gets written to memory. As a bonus, the punched card serves as a record of the bytes that were written to memory, and can be re-used.
124
125 If anything, it’s the technology of card _punching_ that’s more advanced. In the example above, the card puncher has printed at the top, by what looks like a dot-matrix printer, the characters for the values it has punched holes for below. But that’s certainly not necessary; in principle, you could punch out the holes by hand, using a hole-punch.
126
127 ## Simulating loading the code
128
129 OK! Now that I’ve imparted to you what it’s like, I’m going to explain
130 why I’m going to take the liberty of not actually doing it this way, and how I plan to fudge it :)
131
132 This project is primarily about _making_ a new software development environment
133 (using the existing “software development environment” of pen and paper)
134 to be used on a computer. The act of actually _putting_ it
135 there is secondary — still important for context, of course, which is why I described it
136 in detail.
137
138 Also, if all the computer has is front-panel switches and lights, then maybe
139 putting a programming environment onto it isn’t the most useful
140 thing you can do. Yes, it’s easier to write a program in BASIC instead of in
141 machine language, but if you still have to enter your BASIC program, byte by
142 byte, in binary, using switches or by punching holes, that’s still quite a bottleneck.
143
144 My point here is that front-panel switches and punchcard readers can load code into a computer
145 _directly_, at the hardware level. Most other input devices — keyboards, serial
146 ports, etc. — can’t do that; they’re too general-purpose. To load code, they would need to
147 work in concert with some software routines that interpret the input they
148 receive.
149
150 Ah, but a programming environment could contain such software routines! In fact, if the purpose of a programming environment is to make it easier to develop software, then arguably it should let you use these easier-to-use, general-purpose input devices for this task.
151
152 So, since the hardware for this project is going to be emulated anyway, what I would like to do is assume that the machine has, along with **simulated front-panel switches,** some kind of **simulated teletype **attached to it.
153
154 We’ll enter the programming environment into the computer by the front-panel switches. But the programming environment itself will use the simulated teletype to interact with the user.
155
156 The actual architecture will probably look something like this:
157
158 * An emulator for a 6052-based computer (probably a Commodore 64).
159
160 * A little program that simulates front-panel switches, reading in strings of binary digits like **00000100** from the C64 keyboard and writing values (in this case, 4) to successive locations in memory.
161
162 * A pair of machine-language subroutines for reading a line of text from, and writing a line of text to, the simulated teletype. **In principle**, we could write these subroutines so that they actually talked to a teletype. **In practice**, they’ll probably be implemented with calls to C64 KERNAL routines for reading from the keyboard and writing to the screen.
163
164 If that seems rather “cheaty”, well... I agree, it’s not ideal, but I’ve only got a month to finish this :)
165
166 Since this might be the last blog post before I begin, I’ll mention a few other things you can expect from this project.
167
168 * The program will be designed, programmed, and hand-assembled, on paper.
169 * Updates to this blog will consist mainly of photos or scans of those papers... I won’t be writing posts about the design.
170 * I will have a hardcopy of the [Commodore 64 Programmer’s Reference Guide](http://catseye.tc/node/Commodore_64_Programmer%27s_Reference_Guide) which I will feel free to consult, but I’ll try very very hard not to consult the Internet.
171 * I might do a little warmup first (like, “echo the lines you type in”) before starting on the programming environment proper.
172 * The programming environment will probably be very similar to FORTH. I will definitely be trying to keep it small (I will have to enter all these bytes, in binary, at the end!) while aiming to make it easier to program with than assembly.
173 * The programming environment won’t use any features of the C64 except for those two KERNAL routines to simulate a teletype.
174
175 * I won’t hesitate to save the emulator’s state while entering the code, so I don’t have to do it all in one sitting. But... I'll try very hard not to abuse that feature, to e.g. “undo” entering wrong code. (This suggests the programming environment should contain some kind of debugger...)
176
177 And, er, that’s it! Can’t wait to start!
178
179 The warm-up
180 -----------
181
182 _July 3, 2015_
183
184 ![](images/tumblr_inline_nqxhbjR1Zh1tvda25_540.jpg)
185
186 ![](images/tumblr_inline_nqr9iiQmY81tvda25_540.jpg)
187
188 * * *
189
190 ![](images/tumblr_inline_nqr9ipKWZB1tvda25_540.jpg)
191
192 * * *
193
194 ![](images/tumblr_inline_nqr9jfJpBU1tvda25_540.jpg)
195
196 * * *
197
198 All written! Now, to load it (see _Loading the code_ above for details on this)...
199
200 ![](images/tumblr_inline_nqr9kqAnnd1tvda25_540.jpg)
201
202 ![](images/tumblr_inline_nqr9kwi0tG1tvda25_540.jpg)
203
204 ![](images/tumblr_inline_nqr9lkgX0n1tvda25_540.jpg)
205
206 ![](images/tumblr_inline_nqxheuHGdA1tvda25_540.jpg)
207
208 ![](images/tumblr_inline_nqxhfrjk8j1tvda25_540.jpg)
209
210 ![](images/tumblr_inline_nqxhgdnJBX1tvda25_540.jpg)
211
212 A better front-panel simulator
213 ------------------------------
214
215 _July 5, 2015_
216
217 One thing that disappointed me slightly during _The Warm-up_ was that the simulated front-panel loader was not terribly realistic. It lets you backspace to erase bits you’ve typed in, and it leaves a “paper trail” of values you’ve entered, on the screen. It occurred to me that it wouldn’t be too difficult to write something that simulates a front panel better, so that is just what I did.
218
219 The front-panel simulator below works a lot like the 1802 Membership Card front panel (see _Loading the code_ for more details on that.)
220
221 ![](images/tumblr_inline_nr1av8OuMZ1tvda25_540.jpg)
222
223 The screen shows an approximation of 8 LEDs and 8 SPST switches that would be connected to the 8 data lines on a real front panel.
224
225 ![](images/tumblr_inline_nr19f04T6y1tvda25_540.jpg)
226
227 The keys on the bottom row of the keyboard move each switch down; the keys in the 2nd-to-bottom row move each switch up. (In an effort to be more realistic, they are not toggled by a single key.)
228
229 ![](images/tumblr_inline_nr19fai3D41tvda25_540.jpg)
230
231 Pressing Return causes the binary value selected by the switches to be written to the current address in RAM. That value is then reflected in the LEDs.
232
233 ![](images/tumblr_inline_nr19flxudE1tvda25_540.jpg)
234
235 Other simulated buttons (not show in the UI) are
236
237 * `=`, which advances the address by one (you typically press this every time you are happy with the current byte you have written,)
238 * `&` which resets the address to the beginning of memory (which can be used to review the bits you’ve entered by stepping through them with `=` and watching the LEDs), and
239 * `!` to execute the machine code at the current address.
240
241 I plan to use it to enter the machine-code monitor program I’m writing (more on that in a future post.)
242
243 I’ll put the code for this front-panel simulator (and other code from this project) in a repository on Github at the end of the month (or earlier, if someone requests it.)
244
245 Cheatsheets and chickenscratches
246 --------------------------------
247
248 _July 6, 2015_
249
250 I decided, while I was writing all this code by hand, I might as well also write out some stuff about 6502 programming that I can never remember when I need it.
251
252 ![](images/tumblr_inline_nr2d6pZykG1tvda25_540.jpg)
253
254 ![](images/tumblr_inline_nr2d7al9he1tvda25_540.jpg)
255
256 ![](images/tumblr_inline_nr4dif0mwk1tvda25_540.jpg)
257
258 ![](images/tumblr_inline_nr2d7jFcv61tvda25_540.jpg)
259
260 Sketches of the design and code for the machine-language monitor. It was basically written three times; once in pencil, once with a ballpoint pen, and the final version (not shown here, coming soon!) with fineliners.
261
262 ![](images/tumblr_inline_nr2d7pw2iS1tvda25_540.jpg)
263
264 ![](images/tumblr_inline_nr2sx2a8Qs1tvda25_540.jpg)
265
266 ![](images/tumblr_inline_nr2d80BPRW1tvda25_540.jpg)
267
268 ![](images/tumblr_inline_nr2d89ZDc21tvda25_540.jpg)
269
270 ![](images/tumblr_inline_nr2d8lfBmD1tvda25_540.jpg)
271
272 ![](images/tumblr_inline_nr2d90BXxP1tvda25_540.jpg)
273
274 ![](images/tumblr_inline_nr2d9rK7M71tvda25_540.jpg)
275
276 ![](images/tumblr_inline_nr2d9wo2q71tvda25_540.jpg)
277
278 SITU-MON
279 --------
280
281 _July 9, 2015_
282
283 ![](images/tumblr_inline_nr4holCA4X1tvda25_540.jpg)
284
285 ![](images/tumblr_inline_nr4hosyQAs1tvda25_540.jpg)
286
287 ![](images/tumblr_inline_nr4hp8XGSf1tvda25_540.jpg)
288
289 ![](images/tumblr_inline_nr4hpmbakm1tvda25_540.jpg)
290
291 ![](images/tumblr_inline_nr4hpsIKia1tvda25_540.jpg)
292
293 ![](images/tumblr_inline_nr4hpyN6841tvda25_540.jpg)
294
295 ![](images/tumblr_inline_nr4hq8dN861tvda25_540.jpg)
296
297 ![](images/tumblr_inline_nr4hqngl9V1tvda25_540.jpg)
298
299 ![](images/tumblr_inline_nr4hqsGRxP1tvda25_540.jpg)
300
301 ![](images/tumblr_inline_nr4hr03Mce1tvda25_540.jpg)
302
303 ![](images/tumblr_inline_nr4hr8HQh41tvda25_540.jpg)
304
305 ![](images/tumblr_inline_nr4hrdRrgc1tvda25_540.jpg)
306
307 ![](images/tumblr_inline_nr4hrkdfFw1tvda25_540.jpg)
308
309 ![](images/tumblr_inline_nr4hrqEraH1tvda25_540.jpg)
310
311 ![](images/tumblr_inline_nr4hrz45NF1tvda25_540.jpg)
312
313 I love bits. Bits are great when you’re coding and you want 2,000 of something
314 ------------------------------------------------------------------------------
315
316 _July 12, 2015_
317
318 (with apologies to Mitch Hedberg for the title of this post)
319
320 Right! So almost as soon as I finished writing the code for SITU-MON, I started entering it into the emulated Commodore 64, using the simulated front-panel switches. At first this was in dribs and drabs, a few bytes here, a few bytes there.
321
322 ![](images/tumblr_inline_nrdfo71pHK1tvda25_540.png)
323
324 I won't bore you with thousands of screenshots; it all looked basically as described in _A better front-panel simulator_, above. (And for what it would look like in the physical world, watch the video on the _Loading the code_ post.) It’s not difficult, exactly, it’s just tedious and fatiguing.
325
326 Finally, I had entered all 2,000 bits, and I reset the address to the beginning, planning to review the bits I had entered to confirm they were the same bits that were written on the paper.
327
328 To my considerable surprise, they were completely and utterly different bits than on the paper. They were nothing like what I entered.
329
330 Then I realized what had happened. The SITU-MON code starts at $8100, but this is inside BASIC's default memory range, which extends up to $9FFF. Also, the improved front-panel simulator creates a lot of temporary strings compared to the first version. These grew downward in memory and completely clobbered the 250 bytes I had entered!
331
332 So I lowered the top of BASIC memory, and started all over again.
333
334 ![](images/tumblr_inline_nrd1ja5mUa1tvda25_540.png)
335
336 The second time doing this, at least, I was able to enter the bits much more quickly; I had had practice, and had a block of time to myself that I could dedicate to it. And when I reset the address to review the code, it was, in fact, the code I entered.
337
338 Well, mostly. I skipped a byte about 80% through. So, I re-entered the last 20% and reviewed it again. In the second review, I found one wrong byte, but thankfully it was all in sequence and I didn't have to shift anything.
339
340 Satisfied that what was in the computer matched what was written down on paper, I reset the address to the beginning again and... executed!
341
342 And nothing happened. It just hung.
343
344 Thus, the debugging began.
345
346 I pressed RUN/STOP+RESTORE and re-RUN the front-panel simulator — the moral equivalent of pressing a Reset button on a single-board computer which resets the CPU to a known state without affecting the contents of memory.
347
348 But how to debug something like this?
349
350 I looked back to the listing on paper and traced the execution path through it, as best I could, by hand. I couldn’t see where there was a problem.
351
352 The first routine the code calls is `WRITE_PROMPT`. In the front-panel simulator, I advanced to the `WRITE_PROMPT` routine and executed it. And I got this:
353
354 ![](images/tumblr_inline_nrd28fzSOH1tvda25_540.png)
355
356 Yeah, no, that definitely wasn’t in the spec.
357
358 A mild panic set in. The bug could be _anywhere_. I might’ve written down the wrong binary for a hex value; I might’ve written down the wrong hex value for an opcode, or I might’ve made a programming error in the code itself.
359
360 I had just finished entering 2,000 bits on a simulated front-panel — for the second time! — and I was in no mood to spend the rest of the weekend, or possibly the rest of the RetroChallenge, poring over my program.
361
362 So I took a bit of a mulligan. It was a small thing, and I could rationalize it by saying _“let’s pretend there are 16 green LEDs on the front panel for the address lines”_ or something. But still, I’m not proud of it, and it should count against my RetroChallenge score (however vague and nebulous a concept that may be.)
363
364 I converted the address of the `OUTPUTLN_TTY` routine to decimal (33153), dropped to BASIC, and `PEEK`’ed that address to see what byte was there. The first instruction of `OUTPUTLN_TTY` is `LDA #$00`, so I was expecting to see 169 ($A9), but...
365
366 ![](images/tumblr_inline_nrd2u9aQWY1tvda25_540.png)
367
368 Noticing that the byte just _before_ `OUTPUTLN_TTY` was $81, it occurred to me: maybe I made a mistake assigning addresses to labels.
369
370 So I read over the code again, and, indeed.
371
372 ![](images/tumblr_inline_nrd676kT5h1tvda25_540.jpg)
373
374 See the problem?
375
376 So! A bit painful that this mis-numbering happened so early in the code, but, there was nothing to be done except to go through it all and correct the addresses:
377
378 ![](images/tumblr_inline_nrd69wRzNL1tvda25_540.jpg)
379
380 ![](images/tumblr_inline_nrd6ac4zJw1tvda25_540.jpg)
381
382 ![](images/tumblr_inline_nrd6asawdr1tvda25_540.jpg)
383
384 ![](images/tumblr_inline_nrd6b59cBw1tvda25_540.jpg)
385
386 And then, back to the front-panel simulator. Reset the address to the beginning. Keep advancing the address until you get to the next byte that needs correcting, enter the new byte, repeat. A little nerve-wracking, but not terribly difficult, because I was getting pretty used to this by now...
387
388 Then, reset the address to the beginning again, and… execute!
389
390 ![](images/tumblr_inline_nrd66akZir1tvda25_540.png)
391
392 Hey! That looks... like what I expected! Let’s see if it works:
393
394 ![](images/tumblr_inline_nrdcglfU4p1tvda25_540.png)
395
396 It works! It works!
397
398 This is a very nice feeling — one that makes up for the earlier disappointments.
399
400 So now... we have a machine-code monitor! It’s crude and ugly, but it does the trick, and it’s small — 250 bytes, or maybe 251 bytes now, because of the addressing correction? I’m not sure, but it’s still less than 255 bytes, and that’s great.
401
402 ![](images/tumblr_inline_nrdcf8U9We1tvda25_540.jpg)
403
404 We’re not done, though! A machine-language monitor is a _kind of_ a programming environment, but it’s not a very good one. We won’t have to convert anything to binary, and entering lines on a keyboard is a lot easier than using front-panel switches. But we do still need to hand-assemble our code to hex, and compute addresses and so forth, which means we’ll still be using paper a lot.
405
406 Here’s an example of how much easier it will be, though. It’s a fancier version of the warm-up exercise, the “echo” program. It displays a sort of prompt between lines, and lets you quit by starting the line with a period.
407
408 ![](images/tumblr_inline_nrdcfwfVun1tvda25_540.jpg)
409
410 Note that, since we don’t have to convert to binary anymore, we can format the listing on paper more compactly. Entering and reviewing and running it is a matter of a few monitor commands:
411
412 ![](images/tumblr_inline_nrdcwtBdJt1tvda25_540.png)
413
414 And we test it a bit to make sure that it works as designed...
415
416 ![](images/tumblr_inline_nrdcxeiBNf1tvda25_540.png)
417
418 I’m quite happy with this!
419
420 Now, to design and write a _better_ programming environment that we can enter into the computer using SITU-MON here...
421
422 SITU-SOL
423 --------
424
425 _July 26, 2015_
426
427 ![](images/tumblr_inline_nrzvpv3cLI1tvda25_540.jpg)
428
429 ![](images/tumblr_inline_nrzwgcclo91tvda25_540.jpg)
430
431 ![](images/tumblr_inline_nrzvqgXQfp1tvda25_540.jpg)
432
433 ![](images/tumblr_inline_nrzvqyNVaf1tvda25_540.jpg)
434
435 ![](images/tumblr_inline_nrzvrcdNt41tvda25_540.jpg)
436
437 ![](images/tumblr_inline_nrzvsmnZih1tvda25_540.jpg)
438
439 ![](images/tumblr_inline_nrzvrp1ZbY1tvda25_540.jpg)
440
441 Now, the program listing! No, wait — I don’t want you to get the impression that this just appeared fully-formed on paper. So, first, I’ll ask you to imagine about 30 sheets of paper that looked something like this:
442
443 ![](images/tumblr_inline_nrzx8z4FaS1tvda25_540.jpg)
444
445 OK, now the program listing!
446
447 ![](images/tumblr_inline_nrvw3yUlEx1tvda25_540.jpg)
448
449 ![](images/tumblr_inline_nrvw4g36bA1tvda25_540.jpg)
450
451 ![](images/tumblr_inline_nrvupnPebC1tvda25_540.jpg)
452
453 ![](images/tumblr_inline_nrvuprwkNT1tvda25_540.jpg)
454
455 ![](images/tumblr_inline_nrvupwdWX91tvda25_540.jpg)
456
457 ![](images/tumblr_inline_nrvv2u0j8d1tvda25_540.jpg)
458
459 ![](images/tumblr_inline_nrvv318iAj1tvda25_540.jpg)
460
461 ![](images/tumblr_inline_nrvv39RAu01tvda25_540.jpg)
462
463 ![](images/tumblr_inline_nrvv3ejZHU1tvda25_540.jpg)
464
465 ![](images/tumblr_inline_nrvv3lkICJ1tvda25_540.jpg)
466
467 ...
468
469 All written and hand-assembled!
470
471 At this point it’s handy to have a list of the entry points, so I wrote that up too:
472
473 ![](images/tumblr_inline_nrvw5etEln1tvda25_540.jpg)
474
475 ![](images/tumblr_inline_nrvw6d9snl1tvda25_540.jpg)
476
477 Now, to enter it... luckily, entering hex digits with SITU-MON is a lot easier than entering bits using front-panel switches.
478
479 ![](images/tumblr_inline_nrvwdeHmFt1tvda25_540.png)
480
481 ![](images/tumblr_inline_nrvy8qIiJh1tvda25_540.png)
482
483 ![](images/tumblr_inline_nrvy8xy0h61tvda25_540.png)
484
485 ![](images/tumblr_inline_nrvy92hoW91tvda25_540.png)
486
487 ![](images/tumblr_inline_nrvy99cwPG1tvda25_540.png)
488
489 All done!
490
491 Of course, I made several errors.
492
493 I caught one error while reviewing what I had entered with the M command. I had simply mistyped a line. That one was easy to fix.
494
495 Other errors — I had to test the program first.
496
497 And in order to test it, I needed to have a symbal table for it to work on. I made one up with two very simple “commands” whose effect would be both obvious to see, and non-intrusive on the rest of the system. I decided to have them call two of the simpler routines present in SITU-MON (`WRITE_PROMPT` and `INCR_ADDR`). (And yes, you’re right, they should really be called `$ADDR` and `$INC`, with the dollar signs — thank you for paying attention to the spec. But, this was just to test...)
498
499 ![](images/tumblr_inline_nrvv4mqr641tvda25_540.jpg)
500
501 ![](images/tumblr_inline_nrw4c1iXf71tvda25_540.png)
502
503 I wrote the test driver so that I could A8200 then G in
504 SITU-MON, enter a few symbals, and then, after it returned to SITU-MON,
505 `AC100` then `M` to look at the code it generated.
506
507 One obvious symptom during testing was that `SKIP_SPACE` didn’t seem to
508 do anything at all. It turned out that I had completely mis-assembled
509 `LDY LINE_OFF`. (You can see this fix, and all the other fixes, in the
510 listing above, if you look for them.)
511
512 Another one was that the addresses in the generated code weren’t right. It was
513 emitting `JSR`’s to the size-part of the symbal table record, not the compiled
514 code. It turned out that in `LOOKUP_SYMBAL` I had forgotten that
515 `ADD_TO_STAB_PTR` gets its input from the memory location `STAB_DELTA`, and not
516 from the accumulator. Luckily the fix was easy: add a new entry point called
517 `ADD_A_STAB_PTR` just before `ADD_TO_STAB_PTR`, and call that one instead.
518
519 Once I fixed that, I was able to compile simple “programs”:
520
521 ![](images/tumblr_inline_nrw4gcaz1J1tvda25_540.png)
522
523 There was still one more bug. The code generated when compiling a `!` (repeat) was wrong — it was jumping one byte too far back in memory. Once spotted, that was another easy fix. And then...
524
525 ![](images/tumblr_inline_ns3yny81dG1tvda25_540.png)
526
527 ![](images/tumblr_inline_ns3yoeoq9e1tvda25_540.png)
528
529 Huzzah!
530
531 A moderate success. We have, on this emulated computer, a programming environment, hand-written and hand-assembled and hand-entered in hexadecimal (using a less sophisticated programming environment, which was itself hand-written and hand-assembled and hand-entered in binary using simulated front-panel switches.)
532
533 But why do I consider this a moderate success rather than an unqualified success? Well, I’ll write a retrospective blog post on that topic shortly; stay tuned! :)
534
535 Retrospective
536 -------------
537
538 _July 28, 2015_
539
540 What have I learned from this? What would I do differently, if I had to do it all again?
541
542 **Writer’s cramp**. I really didn’t forsee that. I probably should’ve, but I didn’t. My wrist seems OK now, but last week it was definitely a bit ache-y, and I scaled back my ambitions a bit because I didn’t want to stress it too much. I guess it’s been a while since I’ve written this much.
543
544 **Uneven columns of text**. I wrote the “nice” version of the code on printer paper placed over lined paper, to keep my rows straight, but I really should’ve used graph paper instead, to keep my columns straight too. Or [French ruled paper](http://blog.shopwritersbloc.com/notepads_paper/what_is_french_ruled_paper.html), or a [ledger](http://3.bp.blogspot.com/-Dd5xQGuzzRY/UV2v8FgEDiI/AAAAAAAAABg/kOQ7W_Mn8Ls/s800/Cash+Book.png), or something. Also, putting more thought into choice of colours, etc., would’ve been nice.
545
546 **Assembler-ness in hand-assembly.** I only flaunted the fact that I didn’t have to please an assembler’s idea of syntax a little bit: I used the same “local labels” like NEXT: over and over again, since I knew very well which one I meant at each point. An assembler program would’ve wanted me to call them NEXT1, NEXT2 or whatever, to keep them apart. I even used underscores in these labels, purely out of habit, but of course they weren’t at all necessary. I could’ve even gone much further -- I could’ve just drawn arrows from one part of the code to another. I kind of regret not doing something more “artistic” like that.
547
548 **No LEDs for the address lines**. As I mentioned in the _I love bits_ post, it would’ve saved a significant amount of debugging if I had known _what_ address I was entering bits _at_. That’s a definite advantage the nice big front-panel of the [Altair 8800](https://upload.wikimedia.org/wikipedia/commons/0/01/Altair_8800_Computer.jpg) has over the austere front-panel of the [1802 Membership Card](http://www.sunrise-ev.com/membershipcard.htm). But even showing the lowest 8 bits of the address would’ve been useful as a guard against this sort of address-misalignment problem.
549
550 **No padding between routines**. I hand-assembled each routine to start at the very next address available after the previous routine. My excuse was that I didn’t want to have to enter more bytes than I had to. But this is a risky practice, because it’s quite easy to miss an instruction, or to want to insert an instruction later, for debugging; but if there’s no free space after the routine, you need to figure out what to replace with a JMP to somewhere else in memory (which will JMP back to continue the routine), then you need to find somewhere else in memory to put it... it’s a mess. I was lucky in that I didn’t hit a problem that required this. But it was luck. It would’ve been smarter to add 3 or so NOPs after the end of each routine, to make adjusting the routine easier, if needed. Even if it would’ve meant entering 24 more bits each time.
551
552 **No comments**. Yeah, that’s the thing, see. Writing documentation by hand is harder than writing code by hand because documentation is... sentences. The fact that you’re already writing out the “important” stuff seems like a good excuse to leave out the “non-critical” stuff like comments. But the comments _are_ important -- especially in assembly language, where it’s really important to define what each routine expects when it is called, and what the rest of the program can expect when it’s finished (preconditions and postconditions.) If you fail to pay attention to these when writing code that calls that routine, very bad things can happen. Most of my first drafts did include scribbled preconditions and postconditions, but those notes didn’t make it to the final listings.
553
554 **The language is a bit goofy**. And incomplete (no real standard library.) Well, I kept going back and forth on whether I should make a FORTH-like language or a LISP-like language, while at the same time wanting to keep it as simple as possible... and eventually simplicity won out. The resulting design for SITU-SOL has some similarities to [Shelta](http://catseye.tc/node/Shelta), which I suppose isn’t surprising.
555
556 ...
557
558 OK, those are the basic ones. But the big one is:
559
560 ## **A programming language alone does not a programming environment make!**
561
562 See, one reasonable way to interpret the goal of this project of writing code by hand, is to write enough code by hand so that you don’t have to write code by hand anymore.
563
564 But SITU-SOL doesn’t accomplish that goal. If you wanted to write a non-trivial SITU-SOL program... you’d probably want to write it out by hand first!
565
566 :(
567
568 In other words... I probably should’ve just written a text editor instead. Maybe next year?
569
570 Well, that’s not quite a fair assessment, either. Let me explain...
571
572 In the modern world, we’d write our program in our text editor, and we’d assemble it with our assembler program, which is a separate thing.
573
574 But uncompressed text takes up a fair amount of space, and on 8-bit machines, with their modest RAM and slow (or non-existent) persistent storage, that space is at a premium. So programming environments like BASIC do clever tricks like **tokenizing** the source code; an instruction like INPUT, even though it is entered as five characters, can be represented by one byte in memory, and displayed as those five characters again when the program is LISTed. Forth can do a similar trick (although I admit I’m not familiar with exactly how Forth is spec’ed to work, in this regard.)
575
576 So, once I got SITU-MON in, I probably should’ve written a text editor, so that I could design and write and edit further programs directly on the computer, without using paper.
577
578 But once I came across the idea that SITU-SOL’s code could be _both_ compiled _and_ tokenized (i.e., treat `JSR $xxxx` as a “token” that prints out the symbal-name just before $xxxx when it is decompiled, and so forth) -- that’s pretty neat, and I felt I had to go in that direction. (Maybe that’s how Forth works, too. I should look that up.)
579
580 Anyway...
581
582 To achieve this “edit directly on the computer, avoid paper” plateau, there are at least 3 more things the SITU-SOL environment should do:
583
584 * Let you list the symbals that have been defined so far. (Like Forth’s `WORDS`, but I guess it would be called `$SYMBALS` here.)
585 * Let you see the contents of a symbal’s definition, in a human-readable format.
586 * Let you change the definition of a symbal. Or, if you can’t do that directly, let you replace every call to one symbal, with a call to a different symbal, in every defined symbal. (Then instead of changing a symbal, you write a new symbal and replace all the calls to the old one.)
587
588 Now, I _did_ design SITU-SOL to support these things... and I _have_ written code to do these things! I include it below, for completeness. But I don’t think I’ll have the time (or the wrist-stamina) to hand-assemble it and enter it before the end of the month.
589
590 The code for `$SYMBALS`:
591
592 ![](images/tumblr_inline_ns755p3Sz51tvda25_540.jpg)
593
594 Dumping the contents of a symbal:
595
596 ![](images/tumblr_inline_ns755k2lm71tvda25_540.jpg)
597
598 ![](images/tumblr_inline_ns756fINuA1tvda25_540.jpg)
599
600 Replacing all calls to symbal1 with calls to symbal2:
601
602 ![](images/tumblr_inline_ns7565MTzC1tvda25_540.jpg)
603
604 ![](images/tumblr_inline_ns755u00Fn1tvda25_540.jpg)
605
606 Calling those last two routines from the interactive prompt, with `/D SYMBAL` to dump and `/R SYMBAL1 SYMBAL2` to replace calls to symbals:
607
608 ![](images/tumblr_inline_ns756b1crZ1tvda25_540.jpg)
609
610 So, if the point of this project was to write the code by hand, I can indeed say I have written those routines by hand! Not assembled, entered, or tested... but written, yes!
611
612 ## Future work
613
614 I’ve created a [Mercurial repository on Bitbucket](https://bitbucket.org/catseye/situ-sol), which is mirrored in a [git repository on Github](https://github.com/catseye/SITU-SOL), where I’ll be placing the support materials and binary images from this project, and maybe in the future... other stuff, like a disassembly of the code that was entered.
615
616 One of the reasons I entered SITU-MON at $8100 was because when the Commodore 64 is booted with an 8K cartridge attached, that ROM appears at $8000. I didn’t start right at $8000 because I wanted to reserve room for the header (the bit of ROM that tells the C64 "yes, this is a cartridge”) and some routines to do some initialization.
617
618 So, one thing I’d really like to do is make such a binary image. Even if only to use it in the emulator. Because it’d be kind of cool to boot the machine directly into SITU-SOL. But that’s a bit outside of the scope of this RetroChallenge project.
619
620 But after July ends.... who knows?