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.
Readability
[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:
RCL "QES_REGS" ;
CLV "QES_REGS" ;
STO "REGS" ;
RCL "QES_L" ;
CLV "QES_L" ;
STO ST L ;
RCL "QES_T" ;
CLV "QES_T" ;
RCL "QES_Z" ;
CLV "QES_Z" ;
RCL "QES_Y" ;
CLV "QES_Y" ;
RCL "QES_X" ;
CLV "QES_X"
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
Debugging
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
keywords:
hp42s program,
hp42s programming,
hp calculator programming,
namespace problem,
hp42s program readability,
debugging hp42s programs
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].
Links
More
and longer
hp42s programs
can be found
here.
My hp42s
can be found
here.