how to program the hp42s and similar hp calculators


Generally, the predecessors of the hp42s [introduced 1988] had the restriction of only having global variables, no function-local variables. These global variables were also named 'registers' and addressed by numbers [as e.g. in STO 7 ; RCL 7, or STO 07 ; RCL 07 [store stack register x into register 7 (without popping x), recall stored value from there into x (pushing it on the stack)]]. This would lead to the problem of different programs colliding in using (the same) registers.

Another restriction was found in the small stack (depth 4, the stack registers x, y, z, and t). Such a small stack wouldn't allow a use for temporary/local variables, but merely for calculations and parameter passing.

These two restrictions made it difficult for different programs to be usable at the same time (without interfering in their data).

The hp42s implemented (as a novelty) named variables (named program labels were already present with the hp41c [1979]), which made it, together with the ability to copy the numbered global registers as an array [vector, matrix] entity, feasible to separate variable namespaces. These features would make it possible to save register and stack state on entering a program function, in a prefixed, named variable, and restoring them upon leaving a function, being able to use 'local' data in a later invocation of a function of the same program. [Saving and restoring global variables and stack can be wrapped around core code, as shown later.]

The use of namespaced variables was however not so prominent, since they were often used in the context of 'menu variables' and the like, where long and redundant naming isn't desired.


[Longer] hp programs are hard to maintain. Useful programming methodologies such as encapsulation, [application-defined] data structures and OO are not [directly] present. It has not been widely seen to apply compilers and higher level languages.

Dynamic register allocations [and their lifecycles] as well as rather missing symbolic names don't make hp42s programs readable either.

Turning on, putting into programming mode

To turn a hp42s on, press the ON key [the lower left key, which has the semantic of the EXIT ('cancel') key while in running mode]. The display's contrast is adjusted by EXIT-+ or -. Programming mode is entered by shift PRGM. [shift is the orange key, found above the ON key. It can be released before pressing the next key, making it feasible to operate hps with one finger (apart from such things as contrast adjusting).]

To position the current program pointer past any locally used labels, press shift GTO ...

Typical, small, interactive program

A typical input/output loop with a more-or-less simple calculation starts with a local label, does some calculations on the input x (and possibly y, z, t) (optimally without using numbered registers), and issues the output in x (and possibly y, z, t) [then stops; afterwards resumes at start].

E.g.: LBL 01 ; ... ; RTN ; GTO 01

On the hp42s LBL 01 is entered by shift PGM.FCN LBL 1 ENTER (or the less elegant 0 1 instead of 1 ENTER); [0]1 is a local label; smaller local label numbers take up less space (in their byte-encoding, e.g. on the hp42s and hp41c). Other hps have LBL accessible via f LBL (e.g. hp67 [1976], displayed as 31 25 01, f is the yellow shift key) or g LBL (e.g. hp29c [1977], 14 13 01, g is the blue shift key).

RTN (return from function/subroutine) on the hp42s is also found in the PGM.FCN (program functions) 'menu'. RTN stops if the function is used/called interactive, and returns from call if used in a program, which offers flexibility.

The GTO (goto program label) continues at the beginning of the loop, in interactive mode, after R/S [run/stop] is pressed; it's not considered in the non-interactive mode.

Sample: calculating the diagonal of a rectangle, pythagoras

rectangle sides in x, y; output in x:

LBL 01 ; X^2 ; X<>Y ; X^2 ; + ; SQRT ; RTN ; GTO 01

Usage: 5 ENTER 12 R/S , output: 13.0000 , or 3 ENTER 4 XEQ 01 , output: 5.0000 [XEQ [execute] is GSB [go subroutine] on older models]

X^2 squares [the] x [register] (x2, x * x), SQRT calculates the square root (x0.5, x1/2). X<>Y exchanges/swaps x and y. + [arithmetically] adds x and y (postfix (RPN) notation).

Sample: quadratic equation [hp29c/hp19c version, original]

hp29c/hp19c have only a single-digit number of [program] labels and variables ('secondary' registers are addressed by e.g. .1); for the hp42s, use LBL 01 instead of LBL 1, etc. CHS (change sign) is displayed as +/- on the hp42s, R/S (run/stop) is displayed as STOP.

LBL 1 ; STO 0 ; Rv ; X<>Y ; STO / 0 ; / ; 2 ; / ; CHS ; STO 1 ; ENTER ; X^2 ; RCL 0 ; - ; R/S ; X<0? ; GTO 0 ; SQRT ; STO - 1 ; X<>Y ; + ; RCL 1 ; LASTX ; X>0? ; Rv ; Rv ; STO / 0 ; RCL 0 ; GTO 3 ; LBL 0 ; ABS ; SQRT ; X<>Y ; LBL 3 ; R/S ; X<>Y ; GTO 3

Features used here are: stack rolling (Rv, v is a down-arrow, x y z t is moved to t x y z), x duplication (ENTER (or ENTER^, or ^, ^ being the up-arrow)), variable arithmetic (STO / 0, roughly equivalent to RCL 0 ; X<>Y ; / ; STO 0 ; Rv ; LASTX, without affecting/losing t and l though).

Two tests are done, one for D < 0, one for enhancing precision by trying to avoid subtraction of two similar numbers [later test without GTO, i.e. a 'conditional [stack] move']. Testing for D < 0 is not strictly necessary on a hp42s since it supports complex numbers, see solution below.

Snippets: normalizing parameters

How to translate the parameters c,b,a [of the sample above] [on the stack] into p,q [p = b/a, q = c/a], while preserving t:

Rv ; X<>Y ; R^ ; X<>Y ; / ; X<>Y ; LASTX ; /

This is the pure solution; doesn't assume stack depth 4, and doesn't duplicate an unexpected value, not even intermittently.

Rv ; X<>Y ; / ; R^ ; LASTX ; /

Slightly shorter version; does intermittently duplicate one of our values.

RCL / ST Z ; X<> ST Z ; /

Very short version; uses hp42s' arithmetic with a register/stack element [target x], and exchanging x to a stack element other than y.

Sample: quadratic equation [hp42s version]

[Prepending the snippet above to additionally have a,b,c instead of q,p as input:]

LBL 01 ; RCL / ST Z ; X<> ST Z ; /

LBL 02 ; 2 ; / ; +/- ; X<>Y ; RCL ST Y ; X^2 ; X<>Y ; - ; SQRT ; RCL ST Y ; X<>Y ; - ; X<>Y ; LASTX ; + ; END

Usage [a,b,c version]: 2 ENTER 3 +/- ENTER 5 R/S , output: Y: 0.7500 -i1.3919 X: 0.7500 i1.3919

hp42s is able to display two lines of output [no need for programmed R/S here] and working with complex numbers

Usage [q,p version]: 1 +/- ENTER XEQ 2 ENTER , output: Y: -0.6180 X: 1.6180 , shift SHOW: 1.61803398875 [golden ratio]

This version offers two labels as entry points, and uses an END mark that serves the same purpose as the RTN ; GTO 01 snippet. More hp42s register features are used [RCL ST Y]. It uses a layered approach: a,b,c -> p,q -> -p/2,q -> -p/2,D -> x1,x2; results that aren't needed anymore are discarded; no variables are used.

Typical program using SOLVE [hp42s]

hp42s offers the powerful SOLVE and INTEG [integrate] facilities to find solutions to problems without the need for knowing their analytical solution.

LBL "..." ; MVAR "X" ; RCL "X" ; ... ; END

A global label is needed; parameters are passed via declared menu variables.

Sample: quadratic equation [hp42s version, using SOLVE]

LBL "QES" ; MVAR "A" ; MVAR "B" ; MVAR "C" ; MVAR "X"

RCL "A" ; RCL * "X" ; RCL + "B" ; RCL * "X" ; RCL + "C" ; END

Usage [golden ratio sample]: shift SOLVER "QES" 1 "A" +/- "B" ENTER "C" "X" [The ENTER here is needed to distinguish data entry from triggering the calculation.]

The SOLVER makes things easier (but not faster). Singularities etc are automatically handled, however only real [no complex] solutions are found; for the 2,-3,5 sample above it doesn't find the complex solution, does however locate the extremum at 0.75, which is [for the quadratic equation] the real part of the solution.

Snippets: saving stack and registers

Stack and registers can be saved into [quite] unique [global] registers, using a prefix [or a suffix] in their names. This can be seen as a solution to the namespace problem on the hp42s.

Sample using the label above as variable prefix:

STO "QES_X" ; Rv ; STO "QES_Y" ; Rv ; STO "QES_Z" ; Rv ; STO "QES_T" ; Rv ; LASTX ; STO "QES_L" ; Rv ; RCL "REGS" ; STO "QES_REGS" ; Rv

Restore and cleanup:


Installing a new set of registers:

25 ; 1 ; NEWMAT ; STO "REGS"

Sample: gcd (greatest common divisor)

LBL "GCD" ; LBL 00 ; XEQ 02 ; X<>Y ; XEQ 02 ; X>Y? ; X<>Y
LBL 01 ; MOD ; LASTX ; X<>Y ; X!=0? ; GTO 01 ; Rv ; RTN

LBL "GCD" and 00 are the program entry points; 00 is a additional local label, for cheaper access if used as local subroutine. LBL 01: core calculation loop; requires X to be the smaller parameter [checks are done below].

LBL 02 ; REAL? ; GTO 03 ; GTO 04 ; LBL 03 ; X<=0? ; GTO 04 ; ENTER ; IP ; X<>Y ; X!=Y? ; GTO 04 ; X<>Y ; Rv ; RTN
LBL 04 ; "Needs " ; +"positive " ; +"integer" ; AVIEW ; STOP

LBL 02: input check: data type must not be complex/string/etc, must be positive, must be an integer. LBL 03: helper label. LBL 04: show error message, stop.

Alternatively, LBL 02 could adjust data instead of check for validity (handles complex and fractional data):

LBL 02 ; ABS ; IP ; RTN


Position the program pointer to the start of your debug session: in program mode with the up/down arrow keys on a hp42s, with SST/BST (single step, back step) on older hp models; or with GTO .0001 or in run mode [in the above samples] with GTO 01.

Switch to run mode (by shift PRGM or [once or twice] EXIT), single-step through the program by down-arrow/SST; press that key for more than two seconds if you don't want to execute [i.e. only display] the step [NULL is shown].


More and longer hp42s programs can be found here. My hp42s can be found here.

keywords: hp42s program, hp42s programming, hp calculator programming, namespace problem, hp42s program readability, debugging hp42s programs

Eric Laroche / Tue May 16 2006