The Museum of HP Calculators

HP-41C Synthetic Programming

Some of the HP-41C programs in the Software Library use "Synthetic Programming". Synthetic programming is a way of entering program codes that can't be entered directly from the keyboard.



Many of these instructions were intentionally left out because used incorrectly they can confuse the calculator and cause either a lockup or a "Memory Lost" state. (If you get into the former state, you may need to remove the batteries to reset the calculator.)

You should backup anything important before first engaging in Synthetic Programming.

How Synthetic Instructions Work

HP-41 instructions are one or more bytes long. The calculator will only allow certain sequences, but with the tool below, you'll be able create new sequences by entering code that the calculator allows and then grabbing bytes out of this code to create different instructions. These new sequences allow access to additional characters, additional sounds, more alpha editing commands, easy control of the calculator through direct access to system registers, etc. They make it possible to do new things and to reduce the size and execution time of programs. The byte grabber described below will allow you to remove individual bytes from programs you create so the the bytes that remain are interpreted differently.

Creating a Byte Grabber

You can use the following steps to create a Byte Grabber. Make sure to follow the steps exactly. If it doesn't work the first time, try again. Note that the first step is a master clear so save anything important to cards, tape, or disk now!

  1. Remove any accessory modules.
  2. Do a Master clear by holding down the backspace key while turning on the calculator. The Display will show MEMORY LOST.
  3. Assign "+" to the LN key by pressing shift ASN ALPHA shift + ALPHA LN.
  4. Assign "DEL" to the LOG key by pressing shift ASN ALPHA D E L ALPHA LOG.
  5. Press PRGM to witch to program mode. The display should show 00 REG 45.
  6. Start catalog 1 by pressing shift CATALOG 1 and press R/S immediately before the display blinks. If the display blinks, you waited too long. Repeat this step as many times as necessary to get the R/S pressed before the display blinks. (The display will show the .END. instruction both before and after the blink, but you must press R/S before the blink.)
  7. Press the ALPHA key to go into Alpha mode.
  8. Press the backspace key. The display should now show 4094 RCL 01.
  9. Press ALPHA to leave Alpha mode.
  10. Press shift GTO .005 and you should see 05 LBL 03.
  11. Press USER (if necessary) to enter User mode.
  12. Press LOG 003 which uses the assignment you made earlier to DEL 3 steps. You should now see 04 STO 01.
  13. Press ALPHA to go back into Alpha mode.
  14. Press ? A A A A A A (Everything after the first A will probably display as "-"s.) Press exactly 6 A's!
  15. Press PRGM to leave program mode and ALPHA to leave Alpha mode.
  16. Press shift GTO . . (press both dots)

The byte grabber should now be assigned to the LN key. Press AND HOLD the LN key which should display XROM 28,63. Keep holding the key until the calculator displays NULL because you don't want to execute the byte grabber now. This would be a good time to save the calculator's status on a card by pressing XEQ ALPHA W S T S ALPHA in case you accidentally destroy the byte grabber later.

Be careful in using the byte grabber. You may get a "MEMORY LOST" or lock the calculator if you use it incorrectly. If the latter happens, remove the batteries for a few seconds and return them. If that doesn't work, try turning the calculator on a few times with the batteries out or leave them out for several hours.

Using the Byte Grabber

The byte grabber is used in program mode to capture a byte into a text string which may then be deleted. The byte grabber grabs the first byte of the line FOLLOWING the line displayed. For example, key in the following program fragment in PRGM mode:

ENTER    ; Press the ENTER key
1E-6     ; press EEX CHS 6

Even though you pressed just EEX CHS 6, the calculator insisted on prepending a 1 to normalize the number.

Now pack the program by pressing XEQ ALPHA P A C K ALPHA while still in program mode. Press shift BST to back up to the ENTER line. Make sure the calculator is in both PRGM and USER mode and press the LN key which is assigned to the byte grabber. Line 2 will become a strange looking text line. Press SST to see E-6 all alone.

The strange text line is not needed so press BST to return to it and press the back arrow to delete it. The program now consists of:


Which is functionally the same but one byte shorter and a little faster than the unaltered form.

The only purpose of the ENTER above and in the examples below is to provide a place to run the byte grabber since it always grabs a byte from after the line shown. (This is because the HP-41C inserts after the line shown.) In most real programs, you'll just use whatever instruction happens to be ahead of the byte you want to grab.

You can do more than just make programs a little shorter. You can create new TONEs, access internal registers and control calculator features, create characters that you otherwise couldn't etc.

The Byte Code Tables

The museum provides two tables to aid synthetic programmers. The first is a graphic byte code table (~40K) similar to those published in many books. In each cell, the first line shows how a byte is interpreted as a prefix and the second line shows how the same byte would be interpreted as a suffix. By grabbing the first byte of a multi-byte instruction, the suffix byte then becomes interpreted as a prefix byte. The bottom left part of each cell shows the byte in decimal. The graphic table also shows what bytes look like as characters on the printer and the display. The latter is omitted for bytes 80-FF because they are all starburst (all segments on) for these characters and the space is needed to show the suffixes.

The format each cell in the graphic byte table is shown below:

Synthetic Cell

Alternately, you may prefer this HTML byte code table To keep things simple, it doesn't show the display or printer displays for each byte but it does have the advantage that you can use your browser's search feature to find prefixes and suffixes quickly.

Example: A Synthetic Tone

If you wanted to create a new TONE 90 (decimal) instruction, you would find TONE on either byte code table at 9F and then you would find decimal 90 at 5A hex which corresponds to the COS instruction. Thus you need to start with a program that includes IND 31 (byte 9F interpreted as a suffix) followed by COS. So go into PRGM mode and enter:

ENTER         ; just need some instruction to to run the grabber from
STO IND 31    ; press STO shift 31

The STO was chosen as a convenient way of entering the IND 31 which was what we really wanted. Now BST back to the ENTER and press LN to activate the byte grabber. Now press backspace the delete the strange text string left by the byte grabber.

With the STO prefix byte removed, the following 9F byte is no longer interpreted by the calculator as the suffix byte IND 31 but rather as the prefix byte TONE and since TONE needs a suffix, the following byte 5A is interpreted as a suffix 90 rather than a prefix COS. Pressing SST, you'd expect to see TONE 90 but because the calculator's firmware wasn't written to display multiple character TONE #'s, you'll see just TONE 0.

You really have a synthetic TONE 90 however. To prove it, exit program mode by pressing PRGM and press SST to execute the TONE. Now press XEQ ALPHA T O N E ALPHA 0 to hear a true TONE 0.

Synthetic Instructions in Library Programs

When you encounter an instruction in one of the library programs that can't be entered in the normal way, proceed as you did with the TONE instruction above.

  1. Find the instruction as a prefix in graphic byte code table or HTML byte code table.
  2. Note how this byte code is interpreted as a suffix and chose an instruction that will allow you to enter that suffix.
  3. If the synthetic instruction has a suffix, find it in the suffix part of one of the byte tables and note how that byte is interpreted as a prefix.
  4. Enter the dummy prefix instruction, suffix (synthetic prefix) and next prefix (synthetic suffix) into a program.
  5. PACK. (This is not always necessary but a good idea since you might otherwise end up grabbing an invisible NULL byte instead of the one you wanted.)
  6. Use the byte grabber to remove the dummy instruction prefix. Use backspace to delete the strange text string created in this process.

Example: STO/RCL d & b

Register d contains all 56 system and user flags. Being able to RCL and then STO it allows a program to change calculator modes for its uses and then return them easily to the user's preferences at the end.

To key in a RCL d, find RCL in the graphic byte code table or HTML byte code table at position 90. Note that the suffix interpretation of this byte is IND 16 so we'll enter a STO to allow us to enter the IND 16 and delete the STO later.

Now locate d as a suffix (2nd line of each cell) in the byte code table at position 7E. The Prefix code for this is AVIEW so we'll enter that after the IND 16. In PRGM and USER mode, enter:

ENTER       ; This is just a code to execute the byte grabber from
STO IND 16  ; STO shift 16

Now BST to the ENTER, press LN to execute the byte grabber and press the backspace to delete the resulting text string. The program now consists of:

ENTER	; you can delete this too if you like with backspace

Removing the STO code caused IND 17 to be reinterpreted as RCL and AVIEW to be reinterpreted as d. To STO d later, you would do use IND 17 instead of IND 16.

The value returned from the flags register can be safely stored on the stack but should not be stored in a numeric register. This is because the flags register is 56 independent bits that may not represent a valid number or string. Data stored in numeric registers is subject to normalization which forces it to be a valid number or string.

Register b holds the return stack and program counter. You can make a very small and fast infinite loop by entering:

ENTER		; just gives a place to start the byte grabber

Now BST to the Enter, press LN (byte grabber), and press backspace to remove the text string. SST to see RCL b. Now press LN an again remove the text instruction with backspace. The program now consists of:


Now BST back to the RCL b and exit program mode by pressing PRGM. Now press R/S. The program will run forever but the program indicator doesn't move because the calculator only moves it when labels are executed. Press R/S to stop it. (The contents of b will be in the X register which will give you a taste of what non-normalized data can look like.)

Now press SST to step through the program. Notice that the line number keeps growing even though you're looping back. The reason is the the display code always increments the number unless it sees an instruction that would branch to a different location. Since the code doesn't expect you to be stepping through synthetic code, it does the wrong thing. Be prepared for interesting things like this when you use synthetic instructions. (Note also, that backstepping from these non-existent steps may confuse the calculator.)

Extending the Character Set

You can use the byte grabber to synthesize characters that you can't enter from the keyboard including additional punctuation and lower case characters.

Text instructions start with a byte of F0-F15. The first 4 bits specifies that what follows is a string and the 2nd 4 bits specifies the length. The F0-F15 bytes are prefixes and they are followed by 0-15 suffix bytes respectively. Removing a F# byte has the affect of causing the next # characters to turn into instructions.

The characters for the byte codes are shown in the right side of each cell in the graphical byte code table. Note that some characters print differently than they display--another result of HP not expecting users to discover this stuff.

Synthetic Cell

To add synthetic characters to a text instruction, you create the text string in the required length, grab the leading F# byte which converts the string into instructions. Do not backspace over the grabbed text string in this case. Then you edit the instructions, to correspond to the characters you need refering to the byte code table.

To convert the edited instructions back to text, you use the byte grabber again. This time you position the program counter just before the the text string created above. Using the grabber here causes it to grab the F7 text prefix off the old grabbed string. This causes the grabbed string to convert back to instructions and the last instruction is the text prefix from your original string. Thus, the instructions you edited turn back into a string with the characters you want.

One additional complication: The ? (byte code 3F) in the grabbed string turns into an extra STO 15. Backspace over this instruction to delete it and backspace over the the text string created in the last grab. The dash instructions turned into NULLs that won't hurt anything but consume some extra space until the next time you do a PACK.

Example: Adding A Synthetic #

To create the text "INPUT #1" enter the following program

"INPUT X1"      ; ALPHA I N P U T SPACE X shift 1 ALPHA

BST to the Enter and use the byte grabber (LN) but leave the text string that is created. SST through the instructions to find the X which will have become an E^X-1.  Press backspace and then enter RCL 03 in its place. Now BST back to the ENTER and byte grab (LN) again. Now you can delete the new grabbed text line and the extra STO 15 and your program will look like:

"INPUT #1"

Memory Maps

To better understand synthetic instructions, you need to know a little about the HP-41C's memory map which is shown below:

HP-41C Memory Map

The calculator is designed to process and store Binary-Coded Decimal (BCD) numbers. Each BCD digit requires 4 bits to store. Each floating point number in the HP-41C has 10 mantissa digits, 2 exponent digits and two signs. For simplicity, the signs are also given 4 bits of storage each. Thus the calculator is designed around an array of 7 Byte (14 digit) registers. The numbers on the left side are register (not byte) addresses.

Don't confuse the absolute register numbers with the register numbers used in STO and RCL operations. The base address of the user registers is determined when the SIZE command is executed.

Notice that higher-numbered user registers are in higher addressed memory, but programs start from the top of their partition and execute "downward". Many synthetic instructions you'll see refer to the bottom of memory--the HP-41C's status registers which are shown in more detail below:

HP-41C Status Registers

These registers are accessed using the addresses on the left. The bottom row shows how the registers will be interpreted when they are displayed. Remember that the data contained may not format as a normal number. The bottom 5 registers, are the user stack. Working upwards:

Registers M-P: The Alpha Register
These registers are combined to form the single 24 character alpha register. Each characters is entered at byte 0 of register M and any bytes already in the register are pushed higher to make room. The high end of register P is used as a temporary scratch register.
Register Q: Alpha Scratch.
Used temporarily for various purposes such as holding strings for key assignments, holding function names as the user types them etc.
Register Side T: Unshifted Key Assignment Bitmap.
35 bits represent the 35 unshifted keys. When an unshifted key is pressed, the calculator checks here to see if the key has a user assignment. If it does, it looks for the assignment in the key assignments area and the user program area.
Registers a and b: Return Stack and Program Counter.
Most of the bits in these registers hold the 6 level return stack. Bytes 0 and 1 contain the current program counter. When a subroutine is called, the program counter is pushed into the First RTN Pointer and the other RTN pointers are shifted down.
Register c: Memory Pointers.
This register stores the base address of the sigma register, the location of the permanent .END., the location of the first numbered register (R00) and the "Cold Start Constant". The latter is checked frequently and if it isn't set to 169, the calculator assumes a power failure or other disaster has occurred, and it clears memory and resets. When you store data with a STO nn instruction, the calculator adds nn to the Reg 00 pointer in this register to determine the absolute register address.
Register d: Flags.
The 30 user and 26 system flags are kept here.
Register e: Shifted Key Assignment Bitmap and Line Number.
35 bits represent the 35 shifted keys. When an shifted key is pressed, the calculator checks here to see if the key has a user assignment. If it does, it looks for the assignment in the key assignments area and the user program area. The lower three nibbles hold the current program line number for editing. (It isn't valid when the program is running.)

Example: Storing ANYWHERE

Consider the following synthetic program fragment:

X<>c      ; exchange X with c setting the R00 base to X
X<>Y      ; get value to store in Y
STO 00    ; store at location now pointed to by c
X<>Y      ; get the old value of c back into X
STO c     ; restore c before the calculator panics

The above program expects a value to store in Y and an absolute memory register address in X. It then swaps X with c which preserves c and sets the R00 base to X. (This is this easy because the R00 pointer happens to start at the base of the mantissa.) Note, however, that .END. pointer, sigma base register and Cold Start Constant have all been (temporarily) corrupted!

Next it gets the value to store in X and stores it at register 00 (which is now pointing wherever you want - such as a status register, program memory , key assignment area etc.) and then quickly restores the value of c before the calculator notices how messed up it is. (If you single-step this program, you'll get a "MEMORY LOST" after the first instruction.)

If you want to enter this powerful and dangerous program, you should know enough to do it. You'll want to start with a STO IND 78 to get the X<> and a following SDEV will turn into c when the STO is grabbed. For a more complete program for loading bytes anywhere is shown below.

How the Byte Grabber Works

The byte grabber is really just a string assigned to the LN key. When you entered the byte grabber, you made use of a bug in the HP-41 firmware--when you pressed the backspace in step 8 the calculator backed into the system area. When you pressed GTO .005, you positioned the calculator in the key assignment area. Because the calculator thought it was still somewhere in program space, you used programing instructions to replace the "+" key assignment to the LN key with 7 bytes that are inserted each time you press the byte grabber key (LN).

The byte grabber inserts one register (7 bytes) into the program which contains a 7 byte string of the form F7,00,3f,00,00,00,00. The F7 indicates a string with 7 characters (See the byte code table) but only 6 characters follow. As a result, the calculator interprets the first byte that follows as the last character of the string.

The 3f is the "?" you entered when assigning the key. You could use a different key if you like but it's best to select a byte that corresponds to a single byte instruction. ("?" corresponds to STO 15.) The "A"s you entered relates to the LN key so don't change them unless you wish to use a different key for the byte grabber and know the keycode mapping.

Do not use the byte grabber on the .END. instruction or in empty program memory.

The Byte Loader

The byte grabber is an amazing tool and great for times when you need a quick synthetic instruction or two. There are other times, however, when you'd like to enter many synthetic instructions and might prefer a more direct approach. Clifford Stern's byte grabber shown below will allow you to enter decimal byte codes directly into program memory. You're probably not surprised to find that this is a synthetic program so you'll need to use the byte grabber to create it.

The program is listed below, but to create it, start by entering the following non-synthetic instructions:

02  STO IND 16     ; STO shift 16
03  MEAN           ; XEQ ALPHA M E A N ALPHA
04  STO IND 17
05  RDN
06  STO IND L      ; STO shift . L
07  CLD            ; XEQ ALPHA C L D ALPHA
10  LBL 01
11  STO IND 78
12  RDN
13  STO IND 78
14  AVIEW          ; ALPHA shift view ALPHA
15  STO IND 78
17  STO IND 17
18  RDN
19  STO IND 78
21  STO IND 78
23  STO IND 78
24  RDN
25  STO IND 17
27  STO IND 78
29  STO IND 78
30  SDEV
31  STO IND 17
32  SDEV
33  STO IND Y     ; STO shift . Y
34  CLD
36  STO IND 78
37  SDEV
38  STO IND 16
39  RDN
40  STO IND 17
41  SDEV

Now perform the following steps:

  1. Byte grab and delete the STO bytes from lines 40, 38, 36 by going to the line before the STO, pressing pressing LN (in USER mode) and then backspacing the text line that appears. (Or in other words,  press LN and then BS on lines 39, 37, and 35.)
  2. On line 35 press backspace.
  3. Byte grab and delete the STO bytes from  lines 33, 31, 29, 27, 25, 23, 21, 19, 17, 15, 13, and 11 (i.e. press LN and BS on lines 32, 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10.)
  4. Backspace lines 9 and 8.
  5. Grab and delete the STO bytes from lines 6, 4, and 2. (i.e. press LN and BS from lines 5, 3, and 1)
  6. Backspace line 1

Now you've created all the synthetic lines you need. You should have:

01  RCL b
02  STO M
03  "|---*"  
04  X<> M
05  X<> d
06  X<> d
07  STO M
08  X<> d
09  X<> d
10  X<> M
11  STO N
12  X<> N
13  X<> c
14  STO c
15  "|- -"
16  X<> c
17  RCL M
18  STO c

(The only exception is E4 which you should have no trouble creating or you can just leave it as 1E4.) Add additional non-synthetic lines to form:

The Final Byte Loader

01<>LBL 01
02  CLST
03  BEEP
04  STOP
05  GTO "++"

06<>LBL "LB"
07  FS? 50
08  GTO 02
09  1
10  ENTER^
11  ENTER^
12  CLA
13  CF 21
15  -10
16  GTO "++"

17<>LBL 02
18  7
19  /
20  INT
21  FIX 0
22  CF 29
23  ARCL X
24  "|- REGS."     ; text append space R E G S .
25  TONE 8
27  PSE
28  RCL b
29  STO M          ; STO [ when printed
30  "|---*"        ; no spaces in this string, "|-<><>x" when printed
31  X<> M          ; X<> [ when printed
32  X<> d
33  CF 04
34  CF 05
35  CF 06
36  FS?C 07
37  SF 05
38  FS?C 08
39  SF 06
40  FS?C 09
41  SF 07
42  FS?C 10
43  SF 09
44  FS?C 11
45  SF 10
46  FS?C 12
47  SF 11
48  X<> d
49  INT
50  DEC
51  1
52  +
53  .1
54  %
55  +
56  +

57<>LBL 03
58  1.007

60<>LBL 04
61  " "       ; just a space
62  ARCL Y
63  "|-?"      ; no spaces in this string
65  STO M     ; STO [ when printed
66  RDN
67  STOP
68  FC?C 22
69  GTO 05
70  OCT
71  E4
72  +
73  X<> d
74  FS?C 19
75  SF 20
76  FS?C 18
77  SF 19
78  FS?C 17
79  SF 18
80  FS? 15
81  SF 17
82  FS? 14
83  SF 16
84  X<> d
85  X<> M      ; X<> [ when printed
86  "|-**"      ; no spaces in this string
87  STO N      ; STO \ when printed
88  ARCL Y
89  X<> N      ; X<> \ when printed
90  ISG Y
91  GTO 04
92  SIGN
93  X<> c
96  X<>Y
97  STO c
98  R^
99  DSE X
100  GTO 03
101  GTO 01

102<>LBL 05
103  "|- -"       ; no spaces in this string, "|-<>" when printed
104  ISG X
105  GTO 05
106  X<> c
107  RCL M      ; RCL [
108  STO IND Z
109  X<>Y
110  STO c
111  GTO 01
112  END

To allow you to load any byte code in any place, this program changes register c which is a very delicate operation. Check your entries carefully, and back up again. Writing this program to a card before trying it out is a good idea.

Using the Byte Loader

To use LB go to the the location where you want to enter synthetic instructions and enter the sequence:

LBL "++"

The number of "+" lines should be 16 plus the number of bytes you are going to create. (The "+"s are used both to reserve space to be used by LB and they are executed to for counting so don't use a different key.)

If you have some spare cards, create a long sequence as above and record it. This will make using LB a lot faster. (Tapes, disks can serve too. Extended memory modules are very convenient but are subject to loss when you crash your calculator.)

Now press PRGM to switch out of program mode. If you left the program at the XEQ "LB" statement, you can just press R/S. Otherwise press XEQ ALPHA L B ALPHA.

LB will display the number of registers available for loading (there are 7 bytes per register.) LB then starts prompting with the byte number within the current register. Key in the decimal numbers from either the graphic byte code table or HTML byte code table and press R/S. Note that this program keeps critical data on the stack while prompting you for bytes, so don't disturb the stack by pressing ENTER or doing calculations.

When you are done, just press R/S without making an entry. If you run out of space for insertion, LB will stop prompting you.

For example to enter a program containing RCL d, ST* M, and X<> c, enter the "++" sequence above with at least 22 "+"s, exit program mode and execute LB: Your entries are shown below:

1 REGS.       ; no entry here - just tells you you have one reg (assuming 22 +s)
1?    144 R/S
2?    126 R/S
3?    148 R/S
4?    117 R/S
5?    206 R/S
6?    125 R/S
7?    R/S

After the the LB program stops, you can press SST and switch to PRGM mode to see the LBL "++" followed by some remaining "+"s and your instructions. Now you can remove any extraneous "+"s (and the LBL "++") with backspace or DEL and insert any non-synthetic instructions that are needed to complete the program. (Don't execute this code fragment by itself.)

Details On HP-41C Instructions

These comments refer to the graphic byte code table and HTML byte code table. The casual reader may wish to skip to the next section.

Looking at either table you'll notice some interesting features of the instruction set. There are general forms of instructions like RCL and STO at hex positions 90 and 91. Either of these is followed by a byte that contains the register number (BCD-encoded). However, there are also short forms of RCL and STO for registers 0-15 at positions 20-3F. These short forms for common references reduce program size. This is also true for the LBL instruction.

The GTO, XEQ and W instructions at 1D-1F are followed by text strings representing (GLOBAL) alpha labels. For example, GTO "TEST" would be encoded (in hex) as 1D, F4, 54, 45, 53, 54.

CO-CD are GLOBAL label instructions and ENDs and each takes three or more bytes. The first nibble identifies the instruction as a global and the next three digits indicate the distance to the next global. (Globals are chained together in this way so they may be quickly found.) If the third byte is a text prefix (F0-F15) then the global is a label, otherwise it's an END. In the former case,  the key assignment byte (or zero if unassigned) and the label characters follow. (The text length includes the key assignment byte.)

Instructions F0-FF are prefixes for byte strings with the number of characters to follow specified in the second nibble (e.g. F4 would be followed by 4 characters.)

XROM has been shortened to XR in the graphic byte table. XROM instructions refer to functions in plug-in ROM modules. When a program refers to a function in a ROM that is not plugged in the reference will display as XROM i, f where i is the ROM identity number and f is the function number. (A few modules have two IDs.) The XROM is encoded as the nibble A followed by two 6 bit numbers which encode the numbers in binary (not BCD). The ID is restricted to 0-31 but the function number uses the entire 0-63 range. Giving ROMS IDs made them slot-independent.

B1-BF and D0-DF encode two and three byte GTOs respectively. For all of these, only the first nibble is required to identify it as a GTO instruction. Two byte GTOs are available for labels 00 to 14. The first byte specifies that this is a GTO and the label. A second byte follows (initially zero) that the calculator will later fill in with the distance to the target. This speeds execution later. (If the target is not within the distance that can be encoded in the byte, execution is slower.)

Three byte GTOs start with a BYTE of D0 (208 decimal), a byte of zero, and a byte containing the label. In this form of GTO, the second nibble of the first byte and the entire second byte are available for holding the distance to the target. Because the second nibble is filled in by the calculator, three byte GTOs are shown as taking byte codes D0-DF. The three byte XEQs (E0-EF) work in the same way and are entered as E0, a byte a zero, and a byte containing the label.

Prefix AE is unusual in that the suffix actually determines the meaning of the prefix. If the suffix's highest order bit is zero, then the function is interpreted as a GTO IND suffix. Otherwise the function is interpreted as XEQ IND suffix (but with the high bit zeroed since you couldn't use a register above 100 decimal anyway.)

Synthetic Programming Aids

The instructions above assume you have just the basic calculator. To make these tasks a little easier, you should find either a PPC ROM, CCD ROM or a ZENROM and read their user's manuals. These ROMs include synthetic programs that can make the entry of synthetic programs more convenient.

More Information

This text is not designed to fully explain synthetic programming or the internal architecture of the HP-41C. This is just enough to help you to enter programs that use synthetic programming and to give you an idea of what they're doing.

If you do wish to pursue synthetic programming further, there are several books on the subject including:

The first five were used as references for this page.


This text drew heavily on books listed above which in turn drew on the works of: Jack Baldrige, Erwin Gosteli, Roger Hill, Clifford Stern, Phi Trinh, Bill Wickes and others.

The load bytes program was written by Clifford Stern, published in "HP-41 Synthetic Programming Made Easy" and is used here by permission.

Go to the HP-41C
Go to HP-41C programming
Go to the HP-41C software library
Go back to the main exhibit hall