Prompted by the acquisition of a new HP-48G calculator
In the restricted sense used in this article, to program means to create a sequential list of instructions for a machine that manipulates numbers to perform certain tasks. If "number" includes the idea of a continuously varying quantity, then setting up a machine that calculates with such quantities, called an analog computer, is also programming. However, we shall set this case aside and not consider it here. The creation of a formatted list, such as in preparing an HTML script, or selecting certain parameters, as in what is often called "programming" a VCR, is not programming, though it may also call for skill and knowledge. The programmer must choose between a large number of interacting possibilities at each step and use them properly to reach his goal, not simply choose between similar alternatives or follow a set of predetermined rules.
The power of the machine to execute a useful program that may be of a wide-ranging nature, and not restricted to a single task, or a limited variey of tasks, calls for the kind of functionality provided by a machine that deals with discrete numbers, or a digital computer. These numbers may represent or describe a wide variety of physical objects, but in most cases are simply a set of on-off states, or bits. The size of the set handled at one time is called the machine's word length. A word may be interpreted as a binary number, a real number with mantissa and exponent, a Boolean value, or any other such quantity. The interpretation is not an essential part of the machine, but is fixed by the programmer's intentions. The general process of relating the internal representation in bits to the external meaning is called formatting.
A program is a sequential list of instructions. This does not mean that the instructions are executed in a fixed serial order, though they may be, but that whatever instructions are currently being executed are executed one after another until the place of execution is changed by a "jump." This is reflected in the physical makeup of the machine by loading the instructions into sequential locations in storage, and incrementing the pointer to fetch the next instruction. Control of the progress of execution is an important part of programming.
The programmer has constantly in mind the behavior of the machine, and imagines it as he writes instructions, the effects of each instruction fully appreciated. The failure to create this state of mind is the chief reason for the inability of many people to program effectively. Programming deals with the concrete, so it does not require great powers of abstraction, but perhaps intelligence is required to model the machine in the mind, and so is beneficial to programming. Perhaps chess-playing requires similar qualities, but programming is not a competitive exercise, and this should make it even easier. My belief is that programming does not require unusual intelligence, since it is concrete and simple, but rather an ability to see the consequences of actions clearly, and to select from alternatives.
Programming seems to attract the dimmer lights as well, as many commercial applications attest. Because dim lights are cheaper to hire than bright ones, much effort has been expended in making their road less strewn with wreckage, with things like object-oriented programming, top-down design, and programming metrics. However, the results are not particularly pretty or useful, and there is still no reliable way to make programmers from idiots. Most programming today hardly merits being called programming, since it consists mainly of rearranging a set of blocks and filling in blanks to perform well-specified tasks. Someone else, however, must still do the actual programming.
The power of programming lies in the complementary natures of the programmer and the machine. The programmer has judgment, foresight and good sense, but is assailed by blunders and mistakes. The machine makes no mistakes, and executes each instruction with unerring correctness, but has neither judgment, foresight nor good sense.
The facilities for programming a machine are called a platform (the usual sense is that the machine is the platform, but this is not as useful as the definition proposed). Every useful platform must provide certain facilities, of which the essential ones appear in the following list.
The facilities are listed in a rough order of importance, though all should be present in a useful platform. It is remarkable that the essentials are so few, and so general of application. Numbers, or "data" are stored in places where they can be accessed when needed. Named variables associate a name, or label, or address, with a particular bit of data. The datum may change, but the name always refers to whatever happens to be stored at that instant. In a stack, data are stored sequentially, the latest datum occupying the lowest level, called level 1, the "top" of the stack. Succeeding data are at levels 2, 3 and so on, to the "bottom" of the stack at level N. When another item is added, all items previously on the stack are on the next higher level, up to level N+1. When an item is removed, every item goes to the next lowest level, and N goes to N-1. In a stack the address of a datum may constantly change, unlike the case of a named variable. The references to "top" and "bottom" may be interchanged, so should always be explicitly specified, as was done here. We have in mind a stack of plates, say, where the next one is put on the top or taken from there.
The benefit of a stack is easy access; items are stored and retrieved from a fixed address that does not have to be specified each time. Somewhere the location of the top of the stack is stored, a number called the stack pointer, which is automatically used when you put an item on the stack (PUSH) or take one off (POP). The bad side of a stack is that you have to remember where an item is located in it, if you wish to refer to a particular item, and not simply the item at the top of the stack. A stack is an example of a "data structure," and is the most important one. A stack is implemented at the most basic level of a computer, inside the processor. Creating and managing stacks is one of the basic tasks of the programmer.
Input and output, I/O, are the interfaces between the computer and everything else. There must be some way to put numbers in the computer and store them, as from a keyboard. Numbers calculated in the computer must be displayed or used in some way, and this is output. In both cases, formatting is involved between the internal and external representations. For example, we may want to type 25 and store 00011001 in an 8-bit byte as an unsigned or signed integer, or as 00100101 as packed BCD, or as 00000010 00000101 as unpacked BCD. Similarly, 01000101 is displayed as 25 if formatted as packed BCD, or as 69 if a binary integer. This also includes storage in a disk file, but in that case we must carry out negotiation with the operating system to name the file and read or write it correctly.
Processing of numbers is what most people think the main job of a computer is, and indeed it is very important. The platform may only permit 4-function arithmetic, or may offer a wide variety of arithmetic, trigonometric, logarithmic, hyperbolic, logical and other functions. One number may be transformed into another, as log 2 to 0.30103, or NOT 01100110 to 10011001. Two numbers may give a third, as in 1 + 1 = 2, or 23 = 8. 1 AND 0 = 0 if 1,0 are Boolean values, and AND is a Boolean operator. Alternatively, 01011011 AND 010010001 = 01001001 if it is a bitwise AND. Most platforms have a wide variety of processing functions, and it is best to become familiar with them all.
Conditional execution is the only way a platform has to make decisions. Two numbers are compared in some way, usually by magnitude, and the result may affect the sequence of execution. If the magnitudes of two numbers a,b are compared, there are three possible results: a<b, a=b and a>b. Fortran had an instruction that would send the execution to one of three places depending on the result. This reflected a basic operation of the processor in the high-level language, and was very economical of time and storage. It is more usual now to have only two Boolean results, TRUE and FALSE, produced by some comparison such as (a >b)? If a was indeed > b, so this was TRUE, then one thing would be done. If the result was FALSE, then a second thing would be done. The simplest way to implement this is with an instruction that can be explained as IF () SKIP, which means that if the logical expression represented by the parentheses is TRUE, then the next instruction in the normal sequence is not executed, but the following one instead. If the expression evaluates to FALSE, then nothing happens. This, also, is reflected in the basic operation of the hardware. We'll see in a minute how to use this.
Repetitive execution is repeating the same set of instructions, perhaps with different data, called a loop. We might specify a certain number of times to repeat, or some condition may be tested at the beginning or end of the loop. There may be a loop counter that takes a different value for each repetition, perhaps 1, 2, 3 ... N. This value can then be used in the loop. Many kinds of loops can be constructed from simple instructions, such as the IF () SKIP of the preceding paragraph. Many platforms provide pre-defined types of repetitive execution that make programming easier.
Subroutines and functions are sequential groups of instructions to which execution can be sent, with the execution coming back at the end. We might have an instruction SUB (name), that sends execution to the first instruction of the subroutine, which then executes sequentially. The final instruction is RET, which sends execution back to the instruction following the SUB (name). Obviously, this location must be temporarily saved while the subroutine is executing, then used for the return. A stack is the natural structure for saving these return addresses, since it automatically handles the case of a subroutine calling another subroutine. This is very elegant, and a powerful concept. When a subroutine returns, it generally brings with it a value, which can either be used or ignored. A function is a subroutine intended to return a significant value. Procedure is another name for a subroutine. A large program is generally written as a series of subroutine calls, allowing the program to be broken into handy segments. This is modularization, and is a good idea.
Control of execution at the most basic level is the GO TO () instruction that sends control to the location specified in the parentheses, like a subroutine that never returns. The IF () SKIP instruction is usually followed by a GO TO (). If the condition is TRUE, then the program proceeds from the next instruction after the GO TO. If FALSE, execution proceeds at the location pointed to by the GO TO. A loop with a test at the end can be written with an IF () SKIP followed by a GO TO (start of loop). The loop will be executed until the condition is true, when the skip will prevent a further trip through the loop. In most cases in high-level platforms, the GO TO is included in a predefined control structure, such as DO (loop) UNTIL (test). At this level, free use of GO TO is strongly discouraged because it can obscure the program structure. There are still situations in which it is an efficient solution. At lower levels, its use gives programming flexibility, and often the programming structures which hide it are not available. In other cases, the platform may not have a good way of labelling parts of the program for the programmer's use. In BASIC, each program instruction is numbered and can easily be designated. In the HP48, instructions are in a stream and cannot be externally distinguished. These are probably the extreme cases with reference to the GO TO, essential in BASIC and impossible with the HP48. C takes a middle road, with many control structures eliminating the habitual use of GO TO, while labels can be inserted if desired as targets of a GO TO.
A low level platform is one that permits use of all the capabilities of the hardware, and in which machine details (such as addresses) must often be considered. The ultimate low level platform is assembly language, which works with the full instruction set of the processor. A low level program is necessary in any case to allow higher-level platforms to do what they have to do. A high level platform is one in which the data and instructions refer directly to the job at hand, in terms of the application. A high level platform can access only those functions that have been made available for its use by low-level programs, and, in fact, is usually an assembly of low-level subroutines whose details are not available to the programmer, each of which performs a certain high-level task, such as adding two floating-point numbers. BASIC, Fortran, C and the HP48G programming language are all high-level platforms.
An excellent way to learn programming is to become familiar with assembly-language programming. This was best done on 8-bit microprocessors such as the 6502, or 16-bit processors such as the 8086 or 68000, and one is very fortunate if a suitable system is available, usually a single-board computer with I/O to a keyboard and video terminal. Modern processors have become too large and complicated, even though the principles are no different, for this purpose. An Apple II or IBM 5150 PC are excellent platforms for assembly language and BASIC. They offer such an advantage that it would be good to have such systems still manufactured for educational purposes at least. Assembly language and C are an essential foundation for the serious programmer.
The earliest platform designed specifically for learning to program was BASIC. It is rather easy to write a BASIC interpreter that accepts lines typed in by the user and executes them one by one. Lines are stored by line number, named variables are put into a linked list, and a stack is established for computation. Although BASIC was originally run on a "mainframe," it was chosen as a built-in control language for the Apple II (Applesoft), and when the Apple II was cloned by IBM it became the control language for that system as well, present in ROM, and later as the QBASIC program. Both of these are good platforms for learning programming, but the peculiarities of BASIC are not particularly useful.
C is available in any UNIX system, and runs on any PC. Borland and Microsoft both sell versions of C. Programming is best learned in DOS programs. Even the simplest Windows, such as 3.1 is very complex and strange, and more modern versions add secrecy, undocumented areas, poor and confusing documentation, and extreme detail that repel the sound of mind. It is not hard to write a Windows program; what is hard is finding out what hurdles must be overcome, and this has no place in learning programming. C++ has no extra features required or desirable in learning programming, many of which become invisible at low level anyway. The principal new feature is Object-Oriented Programming, which are fetters to prevent unauthorized or inadvertent effects in complex programs where many people meddle. Since some people think this way, such as Windows Weasels, it may have to be learned when working with certain systems. A Windows program written in C may take two or three pages, while a similar program with up-to-date OOP will take fifty pages. Besides, it is now impossible to obtain the information necessary to write programs without great expense. Microsoft found that if the information were released, practically anyone could write programs much better than theirs in short order.
Forth is a very interesting platform unlike all others, based on explicit use of a computational stack, and intermediate between high and low level. It is not popular with the rabble, but I hope is still available. I have not seen a Windows version, and shudder to imagine what one would be like. If one does work, and gives low-level access, it would be a great boon and reason enough to learn Forth.
The HP 48G appeared in 1993, and seems to be still on sale. In fact, mine was purchased in 2003, and prompted the writing of this article. An earlier model, the HP 48S, is similar. Hewlett-Packard has recently dropped the manufacture of scientific instruments, and it is to be hoped that the calculator line has been picked up by some reputable firm. HP should sell the name before completely dishonoring it, having wrung all possible good will out of it. Then we can forget about the whole mess, and leave it to its mission of maximizing profit by any means possible. I have always considered HP products to be solid and reliable, but rather unimaginative and overexpensive, slowly falling behind their competitors since Hewlett and Packard shuffled off this mortal coil.
The calculators are an exception, being very useful and well-made devices. Their excellence is due to the use of RPN and a stack, in which they surpass their strongest competition, Texas Instruments, by an overwhelming amount. The so-called "algebraic" notation is cumbersome and annoying in scientific calculations. A few day's experience with RPN, and the user will never go back to algebraic notation, or so it ought to be. In fact, even engineering students persist in using algebraic notation and favor the cheaper TI products. Few of these students ever develops the skill of programming their calculators, so perhaps HP calculators are wasted on them.
My first experience with HP calculators was in the early 1970's with the famous HP-35 scientific calculator with LED display. This calculator had no programming function, but was a great advance on four-function calculators and started the displacement of the slide rule. The HP-33E of 1978 still had the power-hungry LED display, but offered 49 lines of program. A program was a sequence of numbers and keystrokes, supplemented by direct entry from the keyboard at program halts. This was not a full programming platform, but could be very useful for repetitive calculations. The HP-41C of 1980 had an LCD display, so batteries lasted much longer, and 63 built-in "registers" to store variables and program. Four 64-register modules could be plugged in to supplement this memory. A register could hold a number, or up to 7 operations. All the features of a programming platform were now provided. The program lines were numbered, so GO TO instructions were possible. Programs could be stored or retrieved using magnetic strips. Serious programming could be done with the HP-41, allowing it to tackle complex tasks. A feature added to the HP line at an early date was statistical calculations.
By 1990, the compact HP32SII offered a similar programming platform and 384 bytes for variables and programs. It could work with equations, rational fractions and complex numbers. Built-in routines for solving equations and numerical integration could be used in programs. The programming platform was about the same, with numbered lines and GO TO, which was economical of the limited space. All the calculators up to this point came with a comprehensive Owner's Guide, which discussed programming fully and gave numerous examples.
The HP-48G added many features, and altered old ones. The user memory was 128K bytes, quite an advance on the HP32SII, and allowing ample room for variables and programs. The appearance of six plain buttons on the top of the keyboard was an answer to keyboard complexity and the inconvenience of typing in identifiers for features not appearing on the keyboard. Many menus could be brought up above these six keys, so that selection could be made with a single keypress. The NXT key shows additional groups of six commands. This is the greatest improvement in the HP-48 over earlier calculators. When you write a program, its name appears automatically on a menu, and you can run the program simply by pressing a button. The HP-48 gives strong support to stack operations, which skilled users love and others wonder at. My initial doubts about the HP-48 were soon dispelled as I learned about these features.
The programming platform is quite different from that of earlier HP calculators, but easy to learn if you have mastered the earlier programming platform. Programs are stored as strings of characters between << and >> delimiters. There are no numbered program lines, no way to enter labels, and so no GO TO instructions at all. The designers are probably proud of this, but the inclusion of a label-GO TO facility would have been very powerful and useful, and is a baby thrown out with the bath water for ignorant reasons. Control structures like those in C are, however, provided, and are sufficiently flexible to handle all reasonable demands. All the essential features of a programming platform are included (with the exception of GO TO).
This great increase in programming power is matched by a great decrease in the power of the Owner's Guide. The treatment of programming is brief, incomplete and nearly devoid of examples. Enough is there to allow one to make short, simple programs, but nothing at all elaborate. Although subroutines are mentioned, no information is presented on how to create and use them. Though there is a table of all operations, there is no indication of how to use them. HP does mention that one can buy an Advanced Owner's Guide with such information in it, however. One presumes one is buying a whole calculator, but finds that important parts (especially information) are not furnished. This weaselly behavior is, unfortunately, typical in the computer world, especially from the less reputable companies, and one which the old HP practiced only occasionally. [Their personal computer endeavor was notable for a lack of useful information, which prevented any compensation for their rotten programming, and even the full use of the system. The Apple II and the IBM PC became successes because of the open information. The HP-PC suffered a richly deserved oblivion.]
It is not difficult to bypass this bandit roadblock by experimentation and analogy, and some important features will be described here that were found by this method, with some detailed examples as well. From the information in the Owner's Guide, it appears impossible for a new user ever to learn how to program the calculator effectively. The text was probably written to make this as certain as possible, while not appearing patently perverse.
The HP-48G came with a chintzy grey fabric case that did not even fit well. I found that it fit very well in the genuine Naugahyde imitation leather case that came with the HP-41, and which should have been around the HP-41 when I dropped it on the floor some years ago. I recommend keeping the calculator in the case, and strictly away from coffee. You may be able to dry out a keyboard, but I would not guarantee it, and one drop can mean disaster. The HP-48 uses AAA batteries, an excellent choice. Best would be mercury batteries, but these are no longer allowed.
The processor of a calculator has separate program and data address spaces. It runs the single program in ROM, and all user programs are interpreted, which means they never use the processor's instruction set. User programs can access constants and subroutines from ROM. This arrangement avoids the complications and hazards of several programs executing in the same memory space, which plague general-purpose computers. The HP-48 keeps 12 significant figures. Among the many interesting features of the HP-48, only programming will be discussed here.
The first program in C is traditionally one that displays "Hello, World!" on the screen. We can do the same on the HP-48. I presume you have before you the calculator, and the Owner's Guide, which, except on programming, is quite good. Clear the stack for neatness (← CLEAR). By ← and → I usually mean the magenta and cyan shift keys just above the ON key. Now press ← <<>> to get a pair of delimiters on the command line. You always get opening and closing delimiters; if you don't want one, just delete it (cursor on it, DEL). A program goes between these delimiters. Now press → "", which gives you the delimiters for a text string. Type in Hello, World! using the alphabetic keyboard (press αα to lock alpha input). The H and W are found on the direct keyboard; the lower case letters are on the left-shifted alpha keyboard, as are the comma and exclamation point. Look at the diagram on page 2-3 for the characters.
Press SPC, which separates tokens on the command line (and puts in a space in a string). Now type in PROMPT and press α to exit the alpha keyboard. You should have <<"Hello, World!" PROMPT>> in the command line. If you do, press ENTER to put it on the stack, where it will appear after the 1: for level 1 of the stack. If you don't, press CLEAR and try again. Now press ', and you will get the two delimiters that mark an algebraic expression. Type in HI, holding down α for the two letters, or any way you like to call up the alpha keyboard. This will be the name for the program. Press STO, and you should see the label HI appear on the menu for that directory. Press VAR if some other menu is there.
Press the plain key beneath HI in the menu, and you should see Hello, World! in the message line. The program is still running, waiting for you to start it again. You will see the annunciator HALT to show you that a program is halted (because of the PROMPT command). Restart the program by pressing ← CONT (the ON key). The message and annunciator will disappear, and things will be back to normal. While a program is halted, you can enter numbers into the stack or do anything else you may want before starting the program again. This is the way a program can prompt for input, giving a hint of what it wants. Press the key below HI again, until you realize you can call up the program at any time from this menu with amazing ease.
It is very important to know how to edit and modify a program. If you type in 'HI' (you know where to get the '') and press ENTER, this will appear on stack level 1 without change. Now press ← EDIT and you will see the text of the program between its delimiters. Now the cursor can be moved with the four arrow keys at the upper right-hand corner of the keyboard. It has insert and overwrite modes, as described in the Owner's Guide, like any cursor. Insert is more useful, since it won't destroy anything. The backspace (the white ←, not the blue or magenta arrows), and the DEL can be used to remove unwanted characters, and new ones can be typed in from the keyboard. When you are through editing, pressing ENTER will save the changes. You do not have to STO again. If you make a mess of it, pressing CANCEL will throw away the changes and let you start over again. For practice, change World to your name, and see that it works.
To get the text of HI, we had to enter the name as 'HI'. Type in simply HI and see what happens when you press ENTER. The program HI will be executed, and you will see the prompt string. Clear the HALT by restarting, or with the PRG CTRL KILL key sequence (CTRL and KILL are in the menus). An identifier without '' will be executed when ENTER is pressed if there is a program by that name. If there is no such program, you will get the identifier bracketed by '' on the stack. That's the reason we had to use 'HI' to access the program itself. If the identifier HI appears in a program, without any delimiters, it will be executed at that place, as a subroutine. PROMPT is a subroutine that takes a "-delimited string from the stack, displays it on the message line, and halts execution. All that was necessary to use it was to provide the proper input and put its name in the program.
It is not clear if iterative solution and numerical integration can be done in a program. These are internal programs whose data is supplied by a "form" and not directly from the stack. The relation between programming and many of the features of the HP-48, such as graphing, is not mentioned in the Owner's Guide. Complex numbers and matrices are no problem, however.
The HP-48 knows the values of physical constants, such as the Stefan-Boltzmann constant, 5.67051E-8, with the name σ. To put this value onto the stack in a program, the operation 'CONST(σ)' is used. Note the '' that mean that the expression will be evaluated, not executed, and that the name of the constant goes in parentheses, not on the stack. A table of the names and values of physical and mathematical constants will be found on pages 25-12 and 25-13 in the Owner's Guide. This operation can either be typed in as shown, or found in ' ←EQLIB COLIB CONST α →S. Note that the first thing is to get the expression delimiters by pressing '. The result can be seen in the command line and verified. It is more economical to use these built-in constants than to type in the value of the constant. In fact, the use of literal numbers in a program should be avoided when possible.
Now let's write a program to calculate the value of σT4, the black-body radiance at T K in W/m2. We assume that the value of T has been typed in before the program is executed, so the program can expect to find the value on the stack (if it is in the command line, it will automatically be put on level 1 of the stack). All we need to do is to raise it to the 4th power, get the Stefan-Boltzmann constant, and multiply them. The program is << 4 yx 'CONST(σ)' * >>. The 4 and the yx are typed by simply pressing those keys; any function key will not be executed, but stored in the program the proper way. Name this program 'SB' and STO it. If you now type in 273.15 and press the blank key above SB in the VAR menu, the answer 315.66536981 appears. The program can be ornamented by prompting for, say, "TEMP" at the beginning. Then you execute SB, enter 273.15 when prompted, and ←CONT to get the result.
Within a program, not only are operations carried out in sequence, but the operands for these operations must be made available on the stack. Every operation takes one or two operands from the top of the stack. When execution of a program begins, the input values have been pushed on the stack by the user, or are put there in response to prompts. There is a rich variety of stack operations available to manipulate the quantities on the stack, and the HP-48 has the advantage that the stack size is not limited. On previous calculators, only four levels were available, called x, y, z and t. When the stack dropped, the value of t was automatically duplicated, a feature sometimes of use. This does not happen with the HP-48. Programs that use the stack intensively are more efficient and economical than those that do not, and use named variables, either global or local, instead.
Items on the stack, because they can be more general than just numbers, are called objects. We have already seen that a program can be pushed on the stack as an object. These objects have nothing to do with the objects of object-oriented programming, which are something completely different.
When I first saw the HP-48, I was dismayed not to find the familar stack operations on the keyboard. However, they are there in the stack menu, which appears with ←STACK, with their whole family. Note that this is not →STACK, which you would guess from the colors, which does something different. The stack operations that do not use a parameter from the top of the stack are most efficient. The object on the top can be duplicated with DUP. Another way to obtain the same effect is to use →ARG, which creates a copy of the last argument of an operation that was used. DUP2 makes copies of both level 1 and level 2, so where there was xy there is now xyxy. DROP is on the keyboard instead of the stack menu. It throws away the top object and the rest of the stack moves down accordingly. DROP2 is in the stack menu, and does the same with the top two values, removing xy. ←SWAP interchanges the first two levels; that is, xy becomes yx. OVER copies level 2 into level 1, pushing up the previous objects. That is, xyz becomes yxyz, and a second copy of y is still available. ROT, on the other hand, gets level 3 and pushes the others up. xyz becomes zxy. ROT and OVER are very useful stack operations.
Sometimes operations with a numerical parameter are required. This parameter is obtained from the top of the stack. N PICK copies the object that was at level N before N was entered into level 1, pushing up the other objects. That is, if we start with xyz and want z, we enter a 3, making the stack 3xyz, which becomes zxyz after PICK. ROLL does the same thing, except that the object z is not copied. xyzt becomes 3xyzt and then zxyt. ROT, in fact is just 3 ROLL, but is more efficient. Using PICK and ROLL, we can access any object on the stack. ROLLD rolls down a portion of the stack between levels 1 and N (before pushing N on the stack). 3 ROLLD has the effect xyzt 3xyzt yzxt. Note that level 1 is moved to level N, and the other objects sink down accordingly. Note the difference between ROLL and ROLLD. ROLLD is the old R↓ with the four-level stack, which would be 4 ROLLD. It is necessary to specify the size of the rolldown. The size of the stack can be put in level 1 with DEPTH. The combination DEPTH ROLLD will bring the top object to level 1 and push up the others. It is well worth becoming familiar with these operations by watching what they do. The HP-48 normally displays levels 1-4, so this is easy to do. The HP-48 offers a full set of stack operations, which is highly commendable.
There is also a feature to work on the stack manually, the so-called Interactive Stack, which you call up with →STACK. A menu appears, and there is a cursor to select the stack level. Any level can be viewed and edited, not just the first four. To quit, press ENTER or CANCEL. CANCEL does not throw away changes you have made; to do this, use →UNDO. The things you can do are listed on pages 3-7 and 3-8 of the Owner's Guide. The command ECHO copies the object to the command line. ←CLEAR clears the whole stack (always available on the keyboard). KEEP clears everything above the level that the cursor is on. These operations are not used in programs, but they are very useful for editing objects on the stack. To do this, ←EDIT is used, and it is just like editing a program object as described above.
When you are programming, pressing the menu keys for operations is just like pressing ordinary operation keys. The operation is not executed, but its name appears in the program. Of course, they could be typed in, but using the menu keys is a little easier. It is just as easy to insert any subroutine from a menu in this way.
When a program is executed, the operations are carried out in sequence just as if they were being manually done. The first step in writing a program, then, is to work the problem manually, writing down each step and the corresponding state of the stack. The stack operations necessary will be obvious, and can be written down as they occur. Now you open an object in the command like with << and simply press the same keys, or choose the functions from the same menus. The program will be created before your eyes. It is more difficult if conditional execution or looping is required, but the principle is the same. When you program a certain problem, you will not only have a program that will do the job in a flash, but will understand the problem better. A test example is always necessary to make sure the program is valid, of course.
If a program does not work correctly, the error can be localized by performing one operation at a time and comparing the result with what is expected. This powerful debugging method is available with the HP-48. Call up the program object with '(name)' so that it is in the command line or level 1. The PRG RUN menu contains the debugging commands. DBUG executes the first operation and halts. SST performs a single step, displaying the operation. SST↓ does the same, except that if it encounters a subroutine, it goes right through the subroutine and stops when execution returns. NEXT simply looks at the next operation without executing it. HALT stops execution; this choice is normally used for inserting a HALT when editing a program. KILL stops execution completely. When a program is halted, →CONT will cause it to execute normally. In a large program, you may want to put HALTs at strategic points. When you hit one, you can look at the state of affairs, and single-step if you want. This is a very effective debugging environment that is very easy to use.
Global variables can be used in programs, and are an efficient way to store numbers and constants. To make a variable "C" that contains a value 3E10, just enter 3E10 and press ENTER. Then enter 'C' and press STO. The new variable will appear in the VAR directory for the current directory, shown at the top of the display. That's all there is to it. A complicated way to make a variable using an HP-48 "form" is explained in the Owner's Guide on page 5-6. The HOME directory can be made the current directory by →HOME. The VAR menu will then show the subdirectories, and they can be made current simply by pressing their menu button. A program will look for a variable in the current directory up through the path to the HOME directory. It will use the first variable of the name that it finds. Pressing the menu key for a variable pushes its value on the stack. It is stored in a program as its name. Executing "C" will push 3E10 on the stack.
The Owner's Guide shows how to use local variables that are defined in the program and then used in expressions. These local variables are filled from the stack when the program begins. Local variables exist only while a program is running, and are thrown away at exit. If you name a local variable the same as a global variable, then the global variable will not be available to the program. Begin the list of local variables with →→ (the 0 key shifted blue), which will fill them from the stack. This and other procedures use the algebraic facilities of the HP-48, which are wonderful but not very useful or necessary. Stack operations are always more efficient.
The constant pi may appear as 'π' instead of its numerical value. To make it appear in numerical form, set flag -3. To do this, push -3 on the stack, and then look at ← MODES FLAG. Choose SF and press its button. This gives behavior that seems familiar to me. If you don't like it, just clear the flag again with CF. Flags 1 to 64 are available for the user, and can be set, cleared and tested by programs. The Boolean values returned by the tests can then be used in control statements like IF. System flags have negative numbers, and control the functioning of the HP-48. See pages 4-7 to 4-9. System flags are listed in Appendix D.
The HP-48 is a rich programming platform on which a lot of programming can be learned without a lot of extraneous detail getting in the way. The calculator itself is a marvel, and more entertaining than today's TV.
HP 48G Series User's Guide (Corvallis, OR: Hewlett-Packard Co., 1993). Part No. 00048-90126.
M. Tracy, A. Anderson and Advanced MicroMotion, Inc., Mastering Forth, Revised and Expanded (New York: Brady, 1989).
B. W. Kernighan and D. M. Ritchie, The C Programming Language, 2nd ed. (Englewood Cliffs, NJ: Prentice-Hall, 1988).
J. Sack and J. Meadows, Entering BASIC (Chicago: Science Research Associates, 1973). Or, the IBM BASIC Reference, 6361134 (1984).
R. Rector and G. Alexy, The 8086 Book (Berkeley, CA: Osborne, 1980). Still applicable to the Intel microprocessors, which will run 8086 programs.
Composed by J. B. Calvert
Created 27 April 2003
Last revised 5 February 2004