HP41 Virtual Memory - Terabytes?


Virtual memory architectures are based on swapping "external memory" into actual address  space.
(I am not an expert on this so don't kill the amateur - a building engineer ...)

Owning just a HP41 and a HP71B, both with IL it seems not so easy but ...

Considering synthetic programming: Bringing the instruction pointer in the alpha registers
(M,N,O,P) and executing an INA on the HP41 and OUTPUT :LOOP;X$ on the HP71 where X$ holds the
program for the HP41 would modify the HP41 program on the fly.

I wrote a few small programs (not optimized, just to see if it is possible) and yes it works,
but only in SST mode on the HP41. In RUN mode it simply won't work.. any hint from the
synthetic specialists?

Here some experimental listings, goal of the miniproject: "Hello World" AVIEW.
Big leap target ... a WALL function ??

HP41 Listing:

01LBL "V" Just the label
02 STOPIO seems to clear all IO (IFC HP-IL msg)
03 1 Assumung the HP-71 is #1 (Could also be
anything else sending bytes
05 SF 25 See HP71B listing ...
06 XEQ 01 To bring the program from Alpha regs back via return
07 RTN or STOP, GOTO 'END' or anything else
08 GTO 02
09LBL 01
10 RCL b
11 "` " 96 7 0 0 0 0 0 Instruction pointer => Byte 6 of reg 7 (M)
12 X<> [ X<>M
13 "AAAAA" append just 5 'A' (or anything else)
14 STO [ STO M
15 "AA" append just 2 'A' (or anything else)
16 RCL \ RCL N
17 " |" 167 29 145 124
The instruction code for REG M ... see below
167 29 => XROM 28,29 -> HP41-IL INA function
145 124 => STO b
19 STOP For convenience SST usage (see below)
18 STO b and jump into M (see line 12, falls through '0' bytes'
19 END

The HP71B program:

20 M$=CHR$(167)&CHR$(29)&CHR$(173)&CHR$(25)&CHR$(133)&CHR$(178)&CHR$(130)
40 O$=CHR$(240+11)&"HELLO "
50 N$=CHR$(206)&CHR$(119)&CHR$(113)&CHR$(0)&CHR$(0)&CHR$(0)&CHR$(0)
60 C$=O$&N$&M$
140 O$="WORLD"&CHR$(126)&CHR$(133)
150 N$=CHR$(206)&CHR$(119)&CHR$(206)&CHR$(113)&CHR$(0)&CHR$(178)&CHR$(4)
160 C$=O$&N$&M$

Comments per line:
10 Just to cooperate with the HP41
20 M$ (REG M) holds code equivalent to HP41:
INA 167 29
FC? 25 173 25
RTN 133
GTO 01 178 130 => a COMPILED GTO thus a jump to start of register N (needs
no label, restriction: do not PACK or anything else that destroys
the jump bytes
40 O$ (REG O) holds code equivalent to HP41:
"Hello " 251 + "HELLO" xFB (length 11) as first part of the string
50 N$ (REG N) holds code equivalent to HP41:
X<>O 206 119 And bring O (The "Hello ") to
X<>Y the Y Register
+ 4 NOPS ('0' Bytes) => The Instruction pointer falls to M ...
60 Add the whole bunch for sending
65 Just to follow the 71
70 Send to the 41
140 O$ :
"WORLD" The rest of the "Hello " String (NO APPEND !)
AVIEW 126 Display it
RTN 133 and a normal return (To HP41 V Program line 8)
150 N$ :
X<>O 206 119
X<>Z 206 113 Put 'WORLD' in 'Z'
NOP 0 => to make the compiled goto (next line) easier ...
GTO 01 178 4 => a COMPILED Jump to REG Y, Byte 6 (Left Byte)
170 And send it to the HP41

What happens ... In abstract
In 'V' the bootstrap instructions are loaded for the initial INA function in Line 18
This could be improved with M$ code as in HP71 but I was to lazy ..

In Detail:
<IP> means instruction pointer, located at the byte to start with
Void fields means a '0'(Zero) Byte (<IP> falls through these as NOP)

<IP> falls through ... <IP>
|Byte| 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| M | | | | INA | STO b |

The first INA results in:

|Byte| 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| O |251 (FB)| 'H" | 'E' | 'L' | 'L' | 'O' | ' ' |

| N | X<>O | X<>Y | | | | |
| M | INA | FC? 25 | RTN | GTO 01 (R:N,B6)|

So a jump to N follows to the cuntional code, putting FB+Hello in Y and falls
in M with the next INA resulting in ...

|Byte| 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| O | 'W" | 'O' | 'R' | 'L' | 'D' | AVIEW | RTN |

| N | X<>O | X<>Z | |GTO 01 (R:Y,B:6) |
| M | INA | FC? 25 | RTN | GTO 01 (R:N,B6)|

So assuming INA works fine, code jumps to N and then to Y:Byte 6 where it finds

|Byte| 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Y |251 (FB)| 'H" | 'E' | 'L' | 'L' | 'O' | ' ' |
| Z | 'W" | 'O' | 'R' | 'L' | 'D' | AVIEW | RTN |

Loading "Hello World" in the ALPHA regs (therefore this code is in Y,Z), doing an AVIEW and
return to "V" line 08 (subsequent the XEQ 01 => We preserved the return value in REG b).

Start as follows:
Run the HP71 Program (Output statements are buffered)
Run the HP41 Program, perform the extra R/S to continue after the STOP in 18 => Rubbish in Display

AND NOW ... This works when in SST mode on the HP41 (SST from line 18 onwards or from line 1 ...)
=> A nice "HELLO WORLD" is Aviewed ...
Step until you encounter RTN to return to the "V" program!!
Otherwise your program pointer remains in the status register.

Its a pain in the brain but I can't find the bug... Somebody has an idea??
It could open therabytes of virtual memory for the HP41 of this works

Something like this as boot-trap loading some bigger program doing bigger things doing ....

When it workes, Yes Yes I will, I'll make it an article ....

Best regards



This is wicked cool...

But the HP71 can't handle terabytes, so it would have to be talking to a PC using a HP 82973A. But a PC with an ISA slot probably can't handle terabytes either, so it in turn would have to be using a decent 64-bit server (running Linux, for speed) in order to manage the multi-gigabyte chess program someone will undoubtedly write once this capability is available.

Don't you love this hobby? :)



I got the same results with a HP82164A (RS232) with my humble PC 
with 3TB disk.
The disk cost are about 50% of the price I paid for my HP41CV in
1980 so I'am looking forward to a "best value" upgrade for my
beloved buddy.

Concerning application future: A standard HP41 in the Shuttle
program => I assume NASA grabs the opportunity for Ares ...




I wrote a few small programs (not optimized, just to see if it is possible) and yes it works,
but only in SST mode on the HP41. In RUN mode it simply won't work.. any hint from the
synthetic specialists?


I don't know anything about synthetic programming or details of the HP 41, but I know something about computer architectures. Modifying code is often tricky because the computer assumes just the opposite - that it won't be modified. This lets it do things like keep recently used instructions in cache, or soon-to-be-executed instructions in an internal pipeline.

The upshot is that if you modify the instruction stream, you have to flush the cache and the pipeline. I don't know if the HP41 has either of these things, but your symptom is pretty classic for the problem.

Good luck, and do keep up posted.


Maybe the MCode programmers can give a statement to this?



Fabulous idea! No specialist here, but just a couple thoughts (don't have any HP with me currently but will try your set-up at home and share any further thoughts if I have any)

  1. I think register M is number 5 and not number 7 (T=0,Z=1,Y=2,X=3, L=4, M=5, N=6, O=7). As your line 17 clears all alpha it does not create a problem. Maybe one can use 48/5/00000 in your line 11 for byte 3 of reg 5
  2. very neat and clever separation of the first return address and program pointer and replacement with the wanted program pointer
  3. INA behaves differently depending on Flag 17 on the HP41. If that Flag is cleared, it expects/wait a CR/LF to end the transmission. If it is set, it just accepts the whole string until either alpha is full (24 chars) or the full string has been submitted. Maybe in SST mode the INA gets completed even without the CR sent, but not in Run mode. Have you tried running your experiment with Flag 17 set?
  4. Sorry for being slow, but can you explain the purpose of the Sto B after the INA that you place in Reg M? Doesn't INA wipe out Alpha and hence the StoB as well? As I said, I don't have any HP with me right now so I can't try it out myself, my apologies.
  5. In run-mode, I believe AVIEW has some extra features (e.g. print-out, halt of program depending on some printer flags etc). The other thing I am not sure currently is the treatment of the Alpha-register itself with AVIEW. In Run-Mode the calc normally shows the goose which it does not in SST mode, so I'm not sure if there is something here as well. Have you tried instead of Hello World to e.g. fill some registers with say Pi?
  6. I think there do exist WALL like functions that read/write the complete content of the calc (or subsections like EM, Status regs, user regs etc ) to an HP-IL mass-storage device. To read(write) the whole memory of an HP41 to(from) the HP71 one could simply use on the many available Non-normalized sto(recalls) for each register, rcl M(sto M) and INA(OUTA) but I guess it might take a while.
  7. If you want to use the 71 as a source of a loooong program for the 41, it might be tricky to write a meaningful program that can have no loops >20 bytes (the length of alpha)

Again, fascinating idea, do let us know how it goes!




Hi Peter
1) Yes, you are correct. Legacy from previous experiments
3) Yes, I did, no effect (same "rubbish")
4) Legacy but it would bring IP back to main program where it does
the stop (if inserted) in case INA fails. Better would be to
use the M$ code of the HP71 in M (then 96/5/00000 in line 11 !)
5) I did not try but soon I will -> Keep you informed
6/7) My fantasy goes more in the direction of a small loader that
loads (or writes) a number of registers, moves the curtain
(or vice-versa) and then finalizes the whole thing by
a "GTO ..". Then a WALL or READP, WRITEP look-a-likes could
be possible.
Yes the mass storage functions have these functions and I
have a tape, but also a RS232. The latter would open my
Terabytes disks for my HP41 environment in a total different
e.g.: run a default bootloader on the HP41 (An extended
version of the actual "V") and then the PC can step by step
put the HP41 into a desired state.
Why should we do this: because we can (I hope ..)

Some actual observations:
It looks as if the ALPHA register does not receive (all)
data from the second INA / Output sequence.
I have the feeling that maybe the INA uses some scratch in P.
I'll create a programm that moves the INA into e.g. L
(or ...) but not one of the ALPHA regs and do a
CLA before the INA.

But this next week. Some busy times ...

Thanks for your remarks and help, to be continued




Thanks for the feedback. Seems that F17 did not help but based on your suspicion that the second INA does not receive all I feel more certain that one of two things are happening.

  1. Either the 41 keeps on waiting for the string to finish but does not so in SST mode
  2. Or the two INA's write consecutively into the Alpha reg. It then gets too full and hence the calc does not receive the full amount.

However, if a WALL with a loader-program is your desire, I'm not sure that this way is the easiest possible to achieve this (aside from the pure intellectual pleasure to have programs run in Alpha. In the heydays(?) of the 41, Valentin Albillo developped a whole series of articles which where based on obfuscating programs by running it in Alpha only. The program basically was a series of synthetic alpha strings with a STO b to start the whole program...)

What about the following pseudo HP-41 program to receive the data from the 71:

Lbl 'GetPGM'
'move curtain so that desired program location starts at STO 00
'place number of registers to read from 71 into L
LBL 01
INA 'read in three registers worth to minimize HP-IL overhead
NNSTO IND Y (there are a number of non-normalized STO available
they have slightly different syntax)
NNSTO IND Y (there are a number of non-normalized STO available
they have slightly different syntax)
NNSTO IND Y (there are a number of non-normalized STO available
they have slightly different syntax)
GTO 01
'move curtain to previous position and hence making the stored bytes available.

This is a basic principle that was used for various tricks IIRC.

One thought though: I'm not sure how INA works with non-display characters and if it can be always trusted. Also, I'm not sure if it does not add a '01' in front of each register M/N/O for each set of 6 strings. This would have to be tested.
However, even if that fails, one could do a series of

INA (read in 14 characters representing 7 bytes in hex)
CODE (and one of the many available versions can work)

It would be twice as slow but would definitely work.

Still hope you can figure out what is going on with INA etc, its simply a very cool idea even though I think there might be better ways to achieve what you are aiming for.




Edited: 16 Mar 2009, 10:19 p.m.


Hi Peter & all

Moving the INA part of the code to L and performing CLA before INA helps.

I learned that compiled 2 byte GTO's do not work in Status Regs.
Compiled 3 Byte GTO's do!

My first "Hello World" is there, keep you posted after cleaning up
the code and having time for proper documentation.



Possibly Related Threads...
Thread Author Replies Views Last Post
  Virtual printer for a virtual 41 Mike (Stgt) 6 922 10-30-2013, 10:32 AM
Last Post: Mike (Stgt)
  Virtual HP-IL Video Interface ILVideo the 2nd! Christoph Giesselink 3 699 08-15-2013, 06:49 PM
Last Post: Sylvain Cote
  emulated or virtual? Mike (Stgt) 6 869 05-14-2013, 11:15 AM
Last Post: Mike (Stgt)
  Virtual HP41 and Virtual HP-IL Mike (Stgt) 5 708 09-17-2012, 01:47 PM
Last Post: Mike (Stgt)
  Virtual HP-IL 40 col. video interface simulation Christoph Giesselink 10 1,283 08-19-2012, 06:46 PM
Last Post: Richard Wagoner
  41 User Memory vs System Memory Gerry Schultz 6 926 07-01-2012, 12:02 AM
Last Post: Monte Dalrymple
  RPL, Logo and virtual screen Gilles Carpentier 3 619 04-03-2012, 04:00 AM
Last Post: Oliver Unter Ecker
  HP "Virtual Tech Museum" contest Eric Smith 10 1,106 06-04-2009, 10:06 PM
Last Post: Pal G.
  HP-41CX at HP Virtual Museum Gerson W. Barbosa 2 447 06-15-2007, 09:00 AM
Last Post: Jan
  hp41 vs hp42 memory Fulcrum 17 1,572 04-27-2004, 12:22 PM
Last Post: bill platt

Forum Jump: