Tuesday, April 3, 2018

Making substantial progress understanding original FORTH


I have worked my way line by line through the 202 card images that evolve from the few built in primitives to the working FORTH system. I am still puzzling over a number near the end of the deck, related to commands working with user disk blocks, since these are so interlinked.

One of the design goals of FORTH was to simplify use of computers by eliminating the need to deal with the operating software of the computer. This is starkly visible with original FORTH, where even the file directory structure is bypassed.

Chuck Moore wrote his verbs to manage console and disk I/O to directly manage the hardware, eliminating almost everything in the Disk Monitor System that supported the 1130. To type a character on the console typewriter, Chuck would form the machine instruction to start the I/O, override the interrupt handler to return to another verb and thereby handle everything with no DMS involvement. 

I/O on the 1130 is controlled by the XIO instruction, which points to a two word area that contains a memory address or value, a device address, a command code and a few other flags. The commands are simple - read, write, initiate read, initiate write, control, and sense device are the major ones. 

The difference between a command and its initiate counterpart is that a read brings in a single word at a time, while initiate read starts a read of some length which depends on a DMA like capability where the device will access memory to enter or fetch each word. 

When a device needs attention or has completed a requested I/O operation, it interrupts the CPU. There are a small number of interrupt levels (prioritized with 0 highest). Each level is assigned a core address starting with 0008 for level 0. When the interrupt occurs, the processor executes a BSI I instruction through the address in those low core locations. 

A BSI (Branch and Store IAR) instruction will store the prior instruction address in the target location and branch to the word after (target+1). This is a subroutine call, since the code can return to the interrupted location by an indirect branch through the saved address from the BSI. 

Chuck plugged in the address of a compiled verb into the loc core address to handle the interrupt that will occur when he issues an I/O instruction. For example, the console typewriter and console keyboard use interrupt level 4, which involves low core address 000C. 

Thus, in proto-FORTH, he grabbed the address of a verb to handle the interrupt (e.g. LOC READY to get the address of the verb READY) and stored it as the interrupt handler (STO L  000C)

When an interrupt handle has completed its processing, it returns using a Branch Indirect pointing at the address saved by the BSI that implemented the interrupt. To switch off the interrupt, a special bit is added to a Branch instruction to turn off the current interrupt level. The normal branch is a BSC; with the special bit, it is a BOSC. Chuck's verb READY will return at its end using a BOSC.

He did the same with his user disk functions. The small assembler language program that provides the initial small number of primitives does use DMS to read the card images from disk that extend and complete the language, but once the extension card images are processed, DMS is needed no longer.

Since I/O operations take a relatively long time compared to processing speed, the FORTH code must wait until the interrupt before it continues. Chuck handles this by using a structure he built as a verb QUEUE. It will sit in a wait state (via the instruction WAIT) until the interrupt handler (e.g. READY) modifies the code in QUEUE to become a return to FORTH processing. After building and issuing an XIO instruction, his verb ENQUEUE sets up the QUEUE verb to wait.

Neat, tight and clever code, built up from the card images, taking the few simple primitives of the assembler FORTH core and providing I/O support. It is an example of the design philosophy of the language itself. 

The user can create disk 'files', load and edit FORTH statements and data in those blocks and retreive them to cause them to be interpreted by FORTH. A block may provide additional functionality, such as a more powerful editing system, through extending the language with even more verbs. 

To save space in the limited core memory and dictionary space, these are only added to the dictionary when needed, by a user fetching the block. Useful verbs are available to support extending and dropping such incremental functionality, such as the FORGET verb which drops everything in the dictionary from a target verb onward, freeing the space. 

Disk and editing support involves a group of interrelated verbs and nouns. Data areas like IN which hold the 321 word block from the disk drive, other nouns for line number, sector number and so forth. Verbs such as CREATE, ACTIVATE and DELETE deal with the blocks, while others such as EMPLACE or SEARCH to manage the contents inside a disk block.

One challenge we had with this original FORTH was the lack of the verb that is basic in all subsequent FORTH implementations, the period, which removes the top entry in the stack and prints it on the console. It may be that some set of existing commands provide this capability, but I have not yet discovered how to do this.

Therefore, I wrote my own FORTH verb to extend the system further, and named it period. In proto-FORTH, the period is a primitive that is a synonym for colon as the start of a definition. The card deck used period extensively, but at the end of that deck, I redefined period with my command and viola, original FORTH now has the verb to print the top of stack. 

        10 30 + .

The line above will print 40 on a new line as soon as the period is encountered, removing it from the stack. This makes life much easier as we explore this original FORTH.

No comments:

Post a Comment