HP-41 a M-Code question


Good morning,

does anyone know if it is possible to create
one or several extra register(s) in the ROM of an HP-41
and instructions like STO U RCL U STO V RCL V ... ?

Many thanks in advance.



Your question is a little confusing. You may be confusing synthetic techniques with micro-code capabilities.

Extra registers, accessible through normal HP-41 programs (using functions such as STO and RCL) are available through synthetics, and are limited. Depending on what else is going on in the calculator at the time from 1 to maybe 5 or 6 are available.

The standard ROM of the HP-41 is truly "Read Only Memory" which means that nothing can be written to it, or changed. It is hard coded during manufacture to always be the intended value.

There is such as thing as quasi-ROM (which is special 3rd party hardware) that the HP thinks is ROM, but can be changed using special micro-code functions, again supplied by a third party. But, STO and RCL don't work with such memory, only the special 3rd party functions do.




to expand on Dan's excellent comments - the ability to store data-registers is made available by devices such as the W&W rambox, the Profiset as well as the NoV (and Clonix). In general they are called MLDL devices (Machine Language Development Laboratory IIRC) and they provide what is commonly called QROM (Quasi-ROM) as it actually is RAM.

The above mentioned operating systems provide functions to treat this Q-ROM pretty much the same way as you use X-Memory and allow storage of data-registers, ASCII files and Program files.

If you want specific STO V, STO W functions for convenience, it would be quite easy to implement in MCODE. However, you would never be able to say burn an EPROM with that code as you need the Q-ROM functionality. But you could burn it into a NoV for example. There is a configuration of the Clonix where you have 512 words of Q-Rom available which would be enough to generate a whole alphabet soup of extra registers.

The underlying MCODE function that is uses is WROM (040h) which writes the content of a portion of the C-register to a specific QROM location. Care has to be taken to make sure your MCODE is not portdependent as the user could plug in the Q-ROM in any port. But for simple STO V and RCL V functions, this is quite easy.





Thank you for your responses.

I precisely would like to create a M-code function
( STO U for instance ) that takes the content of register X
and store it in a part of a (quasi) ROM.

I have a HEPAX module that does have the 040 WROM instruction.
However, I don't see what could be the sequence of words to perform that!



There are two different ways you could put this together. The simpler way is to create "STO U" and "RCL U" m-code functions that move the X register to/from a quasi-ROM register that is reserved for that storage. You would have to create two functions for every register (U, S, T, U, etc.) that you would like to use, and the normal -41 STO, RCL, and X<> functions would not be able to access those registers.

The more complex way would be to reproduce the register sto-rcl-exchange functions in ROM, and grab control from the HP-41 system ROM through the use of an polling vector; I believe the CCD module does this, and could be considered a reference. I'm not the expert on m-code programming; I've read some, but never tried it.



Not surprisingly, fully agree with Dan's excellent explanation (and don't be fooled when he says 'I'm not an expert', he is very good at these things!)

Given that e.g. RCL M and STO M are 2 bytes anyway, I don't think there is any pressing reason to try to go the hard way via the polling points. Below is a simple, non-optimized MCODE for a STO function that should get you going. For the RCL function, use the same principle but use CXISA which reads from QRAM. You can find explanations about WROM and CXISA for example here (SDK41 Manual) (BTW - the SDK41 kit is a fantastic MCODE development environment that I highly recommend...)

Basically you reserve a fixed space in your QROM for each register. The version below does this in a very inefficient way - storing only 2 bytes per QROM word and hence using 7 words per register. You can adopt this for your needs if for example you only want to store normalized numbers you can compress the storage. Each word in QROM can only carry values from 000h - 3ffh so you might need dec->hex conversions.

Please be aware the code below is written for simplicity, not tested (so most likely it will have typos and bugs) and not optimized in any way. Nevertheless, I hope it helps.



;Function: STO R
;Input : content to be stored in x-register
;Output: None
;Fixed memory location for storage: p300-p3006
; p is the page where the QROM is plug in / mapped to
[STOR] ?NCXQ [PCTOC] ;bring PC into C[6:3]
RCR 3 ;page number of QROM into C[3]
LDIS&X 300 ;first address for register R storage p300
;as LDIS&X only works until 3ff, if you want to store your values say in AFFh,
;you have to do three LDI’s with setting the pointer to C[2] first
RCR 11 ;=LCR 3. move addr into C[6:3} for WROM
C=0 S&X ;clear S&X where the content pieces go
B<>C ALL ;save into B
LDIS&X 006 ;Load counter
A<>C S&X ;into A
READ 3(x) ;get value to be saved
B<>C ALL ;address into C, value into B
SLCTP ;set up pointers for 2 nyb each
R= 0
R= 1
[WritR]B<>C P-Q ;bring in 2 nyb from B
WROM ;write into QROM
RCR 3 ;need to increment address
C=C+1 S&X ;address for next word
RCR 11 ;= LCR 3
B<>C ALL ;swap address and content
RCR 2 ;move next 2 nyb into pos [0:1]
B<>C ALL ;addr back in C, value in B
A=A-1 S&X ;decr counter in A
JNC [WritR] ;if no carry, rinse and repeat


Hi, Dan and Peter.

Thank you very much for your detailed explanations.
After reading them, I've written the following routines
to store ( and recall ) X-register at the 7 addresses

FD51 097 "W" "STOW" ( I should have inserted a space )
FD52 00F "O"
FD53 014 "T"
FD54 013 "S"
FD55 0F8 READ 3(X)
FD57 130 LDI S&X
FD58 006 006
FD59 106 A=C S&X
FD5A 15C PT=6
FD5C 350 LD@PT- D
FD5D 110 LD@PT- 4
FD5E 290 LD@PT- A
FD5F 0C6 C=B S&X loop
FD60 042 C=0 @PT
FD61 040 WRIT S&X
FD64 23A C=C+1 M
FD65 1A6 A=A-1 S&X
FD66 3CB JNC -07
FD67 3E0 RTN

FD68 097 "W" "RCLW"
FD69 00C "L"
FD6A 003 "C"
FD6B 012 "R"
FD6C 130 LDI S&X
FD6D 006 006
FD6E 106 A=C S&X
FD6F 15C PT=6
FD70 3D0 LD@PT- F
FD71 350 LD@PT- D
FD72 110 LD@PT- 4
FD73 290 LD@PT- A
FD74 31C PT=1
FD75 330 FETCH S&X loop
FD76 0EA C<>B PT<-
FD78 23C RCR 2
FD7A 23A C=C+1 M
FD7B 1A6 A=A-1 S&X
FD7C 3CB JNC -07
FD7E 0E8 WRIT 3(X)

"RCLW" simply overwrites X-register
So, it would be better to replace the last 2 words by

FD7E 028 WRIT 0(T)
FD7F 3B5 ?NCGO goto
FD80 052 14ED roll up

I have some experience in writing maths functions in M-Code,
but I still have many things to learn on handling memory instructions.

Many thanks again,
Best regards,


Love the writ 0, rollup trick! Very cool. One thought: your code currently only works if you have a mldl rom plugged into port 4 and mapped to the f page. I never trust myself to remember such things so I try to make my code port independent, but that's just my preference.

What math functions have you written?





I've written many maths functions in focal programs
and many of them are in the HP-41C library.

A few years ago, I began to study M-Code
and among the routines I wrote, there are for instance:

-Hyperbolic functions and their inverses ( of course )
-FLOOR , X+1 , X-1 , XROOT , Y^X that returns 0^0 = 1
-CBRT ( cube root that returns an integer if the argument is
the cube of an integer )
-Gamma function
-Hypergeometric functions
-Kampé de Fériet functions ( hypergeometric functions of 2 variables )
-DOT & CROSS products, norm of a 3-D vector.
-Product, quotient, square, square-root, inverse of complex numbers.
-Carlson elliptic integrals
-A test that I've named X#Y?? that skips the following line
if X is approximately equal to Y
( to avoid infinite loops when using Newton's method for example )
-Linear regression & linear estimate
-Discrete Hartley Transform

Most of these have been sent to the MoHPC and they probably appear
in the museum at the next update.
I've sent 69 new or updated pages to Dave since 2007
but I don't know when he makes the next update.
These programs are not all written in M-Code, but several however.
Some of them are also for the HP-48.

-By the way, what functions do you have in your own ROM ?

In my HP-41, there are ( currently ) - all in block F

-5 focal programs "EE" equatorial-ecliptic conversion
"KPL" to solve Kepler's equation
"GEO" to compute geocentric coordinates
"R-S" & "S-R" rectangular-spherical conversion

-And 59 M-code routines, namely:

LCB to perform the calculations needed to play "le compte est bon"
that is a French TV game
SQRTF square root of n! ( I've remarked that the HP-41 calculates
99! correctly )
GAM gamma function
RND0 rounds X to the nearest integer
J2000 computes the number of days since 2000/01/01
STOW and RCLW ( extra-registers )
HGF+ hypergeometric function ( including regularized functions )
KdF ----------------------- of 2 variables
SH CH TH ASH ACH ATH ( hyperbolics )
FRC2 that returns x - floor(x)
X+1 X-1
RAND a random number generator that uses the TIME module
AA and BB which are 2 functions to play TONEs
( I've used them in a program that plays the Star Spangled Banner )

X=N? to test if a number is an integer

8X/5 that simply calculates 8 x / 5 ( useful for 3-point Gaussian integration )


VM View Mantissa ( actually written by Ken Emery )
SORT that sorts numbers in contiguous registers
( This routine is already in the 41C-library )
LCO to move or swap a block of registers
MN? to play faster "mastermind" ( or "superbagel" )
3X X/3 and X^3
RF RJ RFZ RJZ ( Carlson elliptic integrals )
CNK to compute binomial coefficients
ST<>A to swap registers X Y Z and synthetic M N O
PR? that tests if a number is a prime
9999999967 is tested in 7m10s
Z*Z Z/Z Z^2 SQRTZ 1/Z ( complex operations )
CARD that simply returns a pseudo-random integer between 0 and 12
DEG F to return the degree of a polynomial from its control number

and several constants:

GAMMA Euler constant
MAXR 9.999999999 E99
KG gauss' gravitational constant
OB obliquity of the ecliptic on J2000.0
HUBBLE Hubble's constant ( more exactly Hubble's time )

-Almost all of them should appear soon in the museum.

Best regards,



Wow, that's an impressive list, awesome! Did you send to Dave just the compiled ROM or the actual listing with comments as well? Given my limited knowledge I find it very hard to understand MCODE listings without any comments...

I'd love to take a peek at your code if possible.



Possibly Related Threads...
Thread Author Replies Views Last Post
  HP-41(CL): The easiest way to transfer FOCAL programs from a Linux PC to the HP-41 Geir Isene 13 1,016 12-05-2013, 02:40 AM
Last Post: Hans Brueggemann
  HP PRIME: APP program code DISAPPEARS !! Joseph Ec 0 198 11-25-2013, 11:35 AM
Last Post: Joseph Ec
  Non-Prime question alert: Hp-41 and synthetic instructions Marcel Samek 11 777 11-04-2013, 09:31 PM
Last Post: sjthomas
  Where to the 32-bit version of User Code Utiltiy for HP-41 ? Olivier (Wa) 2 256 09-26-2013, 01:55 AM
Last Post: Olivier (Wa)
  A HP42S Code Editor Andreas 9 699 09-22-2013, 03:17 AM
Last Post: Andreas
  Dynamic Gaussian Quadrature code in Excel VBA Namir 4 381 07-30-2013, 07:37 PM
Last Post: Namir
  HP-65 Morse Code Dan Lewis 7 490 01-29-2013, 05:22 PM
Last Post: Mike T.
  hp 41 series wire-wrapped connector question. Matt Kernal 3 281 06-19-2012, 01:48 AM
Last Post: Luiz C. Vieira (Brazil)
  [WP34s] undefined OP-code fhub 21 1,000 04-28-2012, 04:09 AM
Last Post: Marcus von Cube, Germany
  Re: HP-41 Navigation PAC question Timo 0 140 02-27-2012, 04:06 AM
Last Post: Timo

Forum Jump: