So far we’ve only dealt with the internal format. Every aspect, including test programs, has been handled in assembly language code.
With conventional machine code, we would use the numbers known as addresses to reference data and instructions; and we would use numbers to represent each instruction atom. However, there is no absolute numeric definition of the instructions, either in absolute numbers or in absolute addresses or offsets. So it seems more convenient to use some kind of human readable format for loading programs.
For now, I’ve settled on a fixed-size instruction format, quadruples. Extra operands are added to pad instructions to four atoms. The extra operands are ignored by the interpreter. One “instruction” known only to the “boot loader” is the label instruction. Even with this simple format, it takes four passes to construct the full instruction list and label bindings (in the form of Lisp lists) without subroutines. Getting a development system up and running currently had higher priority than creating coding idioms.
The label bindings are kept in a table that is private to the boot loader. Before the instruction list can be executed via IFGO, the label bindings must be passed on to the interpreter. One solution is to extend the IFGO instruction to allow the replacement of the current association list. Another solution is to simply write another interpreting layer on top of the base interpreter, which bypasses the problem. A third solution is to hack the bindings using dynamic code.
Dynamic code is the set of instructions created by the base code and executed in the same process as the base code. The reason for using dynamic code is the lack of indirection when binding. When we have a label binding binding = (lbl . ilist) in the label table, we want to introduce the binding to the interpreter as if we were using the Lisp SET function: set[quote[y]; car[binding]]; set[y; cdr[binding]]. Our instruction set only allows the SETQ binding set[quote[y]; cdr[binding]], so the instruction for set[quote[lbl]; cdr[binding]] will need to be constructed, and then executed.
After solving the label binding problem, further development of the programming system does not require direct use of assembly language. We can generate assembly code if we need to create a new base system.