The Museum of HP Calculators
by Robert M. Miller
THE FORTH/ASSEMBLER PAC for the HP-71B Computer provides users with an alternate programming language and allows them and third-party software suppliers to customize the machine for special applications. Four major features are supplied by this 48K-byte plug-in ROM:
The development project that produced the HP-71B's FORTH/Assembler Pac had four objectives:
The language/operating system that was finally chosen to satisfy the design objectives was FORTH, a threaded interpretive language which was developed by Charles Moore for instrument control at the Kitt Peak National Observatory. It has since become very popular for controller applications and is gaining in popularity as an application language for portable and handheld computers.
FORTH is an interpreted language like BASIC in the sense that a line of commands and data can be typed in and executed immediately. However, it is also a compiled language in that new commands (called words) composed of other words and data can be compiled as a series of addresses to be executed. The new word can be used just like any of the existing words and can be executed directly from the keyboard or compiled into the definition of future words.
The design investigation found FORTH to be an extremely flexible tool. Unlike other languages that have a limited number of structures with which to accomplish all of a user's applications, a programmer can extend a FORTH implementation to provide the structure or tools exactly needed to accomplish the task at hand. Also, FORTH is very fast--typically 5 to 10 times faster than HP-71B BASIC, depending on the application. The fact that FORTH is memory efficient was also a consideration in its selection. Even with its many extensions to the standard FORTH implementation, HP-71B FORTH requires less than 16K bytes.
Finally, it is easy to program in FORTH. The language enforces structured programming practices and encourages the development of applications as a collection of smaller tasks. The interpretive aspects of FORTH allow each of these subtasks to be debugged easily. Applications can be quickly modeled as a series of secondary words (words composed of other words). Then, if the application has a speed-critical path, the words involved can be rewritten as primitive words (words written in assembly language). This kind of development has two very worthwhile benefits: only selected portions of an application need to be written in assembly language, and each task is essentially independent of the other pieces of the application and thus has fewer unintended side effects.
The most interesting design challenge was making FORTH peacefully coexist with the HP-71B's BASIC environment. Most FORTH systems are takeover systems in that they supersede any built-in operating system and file system. However, on the HP-71B, BASIC is hard-configured--it occupies addresses 0 through 1FFFF. It was necessary that users be able to switch between FORTH and BASIC and have BASIC programs and TEXT and DATA files in memory remain undisturbed by the actions of FORTH.
A further complication was that, while FORTH typically deals with absolute addresses, the HP-71B dynamically configures plug-in modules in the address space depending on their size and the port in which they appear. Thus, a typical HP-71B module cannot depend on being configured at a particular fixed address. To make matters worse, RAM files also move in memory. If a BASIC program grows or shrinks, all files in the file chain above it shift accordingly. And the address in RAM where a user's files begin also changes depending on the number of ROM and RAM modules plugged into the HP-71B.
Coupled with the above considerations was the desire to make use of some of the functions and features provided by BASIC without having to duplicate them in FORTH. The design objective was for FORTH words to be able to execute a function, a statement, or even a program in BASIC, and then return a result to FORTH. Given that the interface was to be provided in one direction, it also seemed appropriate to allow BASIC to have FORTH execute a word or series of words and return a result to BASIC.
In researching the first problem, that of dynamic allocation of ROM address space and the shifting RAM space, the preliminary decision was to live within the imposed limitations of the HP-71B memory management scheme. Working with the dynamic allocation of address space presented a number of unsavory problems. First, addresses of words compiled into new words could not be absolute addresses; instead, they had to be offsets from the base address of either the RAM or the ROM portion of the dictionary. The high bit of an address acted as a flag to determine whether the offset was to RAM or ROM.
The basis for FORTH's execution speed is the small overhead (in machine instructions) needed to get from word to word. This overhead code, typically called the inner loop, is crucial to a high-performance FORTH system. In a worst-case situation it is possible for a secondary word to spend as much as 50% of its execution time in the inner loop. The typical action of the inner loop is to fetch an address from a memory pointer, then fetch the address contained at the first address, and then start execution at this second address. In this implementation, it is necessary to test the high bit of the first address fetched and, depending on the result of the test, add in either the RAM or the ROM base address. It is then necessary to perform the same test and add on the second address fetched. These additional operations result in a 35% average increase, compared to an absolute addressing scheme, in the number of CPU cycles to execute the inner loop and thus cause an unacceptable speed degradation.
Luckily at this time during the project, the BASIC operating system code had not yet been released and the operating system software design team was persuaded to modify the module configuration algorithm to accommodate the needs of FORTH. In the final version, whenever the HP-71B's configuration code sees a module that is hard-addressed at E0000, it does not configure any modules in the address space between E0000 and FFFFF (64K bytes). This allows the FORTH kernel and assembler to be hard-configured in this address space, thus solving the problem of absolute addresses for the ROM portion of the FORTH system. The remaining parts of the FORTH/Assembler Pac--the editor, FORTH initialization, and the KEYBOARD IS... statement--are contained in a soft-configured ROM, which is handled normally by the BASIC operating system.
It was obvious from the beginning that the FORTH system variables and the user's dictionary entries would have to exist within the file structure of the HP-71B BASIC system, yet always reside at the same address. This was resolved by using the FORTHRAM file, which is always the first file in the file chain in the main memory. Directly below the main memory file chain (in lower memory) are the BASIC operating system's configuration buffers containing information about the number and size of the modules plugged in. These buffers have a minimum and a maximum size, and the starting address of the main file chain depends on the current size of these buffers. When FORTHRAM is created, the difference between the maximum and the current size of these buffers is computed. This amount of memory is allocated as padding to sit between the FORTHRAM file header and the FORTH system information. Whenever the BASIC system performs the configuration code, it finishes by sending out a poll informing other modules that the system has been reconfigured. FORTH intercepts that poll, recomputes the difference between the maximum and current size of the configuration buffer, and adjusts the amount of padding accordingly.
Another issue faced by the design team was compatibility with other FORTH systems. Most FORTH systems were developed for byte-oriented machines (where addresses are 16 bits long and an address specifies a unique byte), but the HP-71B is a nibble-oriented machine with 20-bit addresses in which an address specifies a unique nibble. It was determined to be more in keeping with the idea of FORTH to customize FORTH for the HP-71B rather than enforce an arbitrary scheme where a 16- or 32-bit quantity would refer to a 20-bit address. Therefore, all addresses and data items used by the HP-71B FORTH system are 20 bits wide. This increases the size of FORTH secondaries (since all addresses are 5 nibbles instead of 4 nibbles long), but it allows access to the full address space of the machine.
A more far-reaching change was initiated because of the portable nature of the HP-71B and its multiple file system. Unlike other FORTH systems that are disc-based, a frequent mode of operation of the HP-71B is as a stand-alone unit remote from any type of mass storage. This led to the conclusion that the idea of a "screen" (the traditional name of a FORTH source file) would have to be modified. In disc-based systems, the screen is a 1K-byte block of space on the disc divided into 16 lines of 64 bytes each. Programs shorter than 1K bytes still consume the entire block and the 1K-byte size prevents the creation of longer programs. To obtain maximum flexibility for a RAM-based system where space is constrained, the idea of a screen was modified to mean any legal HP-71B TEXT file. This allows screens to have an arbitrary number of lines, each of which can be up to 96 characters long. (The 96-character width, which corresponds to the size of the display buffer, is constrained by FORTH and not the HP-71B TEXT file type.)
Three "mass memory" buffers, provided within FORTHRAM, are used to compile/execute (called "loading") screens. The loading of screens can be nested (i.e., any screen can contain words that cause another screen to be loaded), since the information necessary to reposition the FORTH system is saved on the FORTH return stack. FORTH will also load files directly from a mass storage device (such as the 82161A Digital Cassette Drive) without requiring the file to be copied into RAM first.
To make use of the HP-71B's excellent floating-point calculation capability, a full set of floating-point words is provided. HP-71B FORTH implements an HP-style floating-point RPN (reverse Polish notation) stack (X, Y, Z, T, and last X registers). The contents of these registers can be manipulated by the FORTH floating-point word set, which duplicates the function set on the keyboard of the HP-41C Handheld Computer. Also, floating-point constants and variables can be created, and words exist to move data between the floating-point and integer stacks. This floating point implementation provides a bridge to the HP-71B for users who are accustomed to HP's RPN calculators.
One of the traditional uses of FORTH is in controller applications. HP-71B FORTH provides this capability in conjunction with the HP-71B's HP-IL module. Specifically, FORTH implements words that correspond to the BASIC commands ENTER and OUTPUT. The FORTH words ENTER and OUTPUT allow a user's application to send and receive data from a device connected to the HP-71B via the HP-IL. For other HP-IL operations, a FORTH program can use any of the 82401A HP-IL Module s functions through the FORTH/BASIC interface.
There are four FORTH words that pass a string of characters to the BASIC environment. BASIC evaluates the string as if it were an expression or command typed in at the keyboard except that, instead of displaying the result, it is put on the BASIC math stack. FORTH retrieves the result and returns the value to the appropriate FORTH stack. It is also possible to invoke the BASIC interpreter and have it run a program or edit a line into a file. In all cases, control returns to FORTH after BASIC has finished its assigned task. These FORTH words are:
Some examples of the use of these words are:
The FORTH/Assembler Pac provides analogous BASIC commands to retrieve values from the FORTH data and floating-point stacks and also allows a user to pass a character string containing FORTH words and data to the FORTH environment for execution:
Some examples of the use of these words are:
Most FORTH assemblers are written in an RPN format, as is FORTH, and the opcode for each machine instruction becomes a FORTH word. The drawback to this approach is that it requires an understanding of FORTH to use the assembler and, typically, such assemblers allow few forward references to unresolved labels. The design team decided to make the HP-71B assembler a two-pass assembler using the standard opcode operand format. Since the assembler creates a symbol table during the first pass, there is no limit on the number of forward references allowed. The assembler contains a wide range of pseudo-opcodes to facilitate the creation of either FORTH words, LEX files, or BIN programs. FORTH words are compiled directly into the user's dictionary. For users who wish to create new keywords and LEX files, a three-volume document is available (HP-71B Internal Design Specification) that describes all of the supported operating system entry points, including their entry and exit conditions, as well as information on system data structures. In addition, hooks were left in the assembler to allow for the processing of new pseudo-opcodes. This allows expansion of the assembler's capabilities to handle specialized tasks.
The source for the HP-71B assembler uses HP-71B TEXT files created by the editor. The source can exist either in RAM or on an external device. A listing file can be generated and sent either to an external printer or to a file in RAM. A difficulty in developing the assembler was that it was written using a language and system that were themselves under development. The FORTH kernel and the assembler were developed concurrently and so it was often the case that slight modifications to the FORTH design caused a ripple effect in the assembler with undesirable results. However, the concurrent development also had the beneficial effect that various words and structures could be added to facilitate the action of the assembler. Furthermore, the assembler is an application program that provided valuable testing of the FORTH Kernel. For example, the FORTH words to create, find, expand, contract, and kill general-purpose system buffers were added specifically for the assembler. These buffers are used to hold variable space needed by the assembler. When the assembler is finished running, this space is reclaimed.
It was the careful and friendly design of the HP-71B BASIC operating system that allowed FORTH to be developed so quickly and to be so powerful. System polls were always in the right place when we needed them, as were hooks into various system routines. The FORTH/ BASIC interface capability would not have been possible had not the designers of the BASIC operating system allowed for the possibility of parsing and executing BASIC code from an arbitrary location within system RAM.
Gabe Eisenstein contributed to the design and implementation of the FORTH kernel. The assembler was designed and implemented by Geoff Mchols. Nathan Zelle wrote the KEYBOARD IS... code and Thaddeus Konar wrote the editor.