Article 1312 of comp.sys.handhelds: From: alonzo@microsoft.UUCP (Alonzo GARIEPY) Subject: Introduction to HP 48SX Internals Message-ID: <52059@microsoft.UUCP> Date: 6 Mar 90 20:50:28 GMT Organization: Microsoft Corp., Redmond WA Introduction to HP 48SX Internals (C) 1990, Alonzo Gariepy ======================================================================== Following is some information that may be useful if your interests run to machine language. Misapplication of the information contained in this document may result in corruption of memory and even damage to the hardware. Backup the contents of your HP 48SX if necessary. Objects ======= Address Type Name Example Display Syntax (if different) ----------------------------------------------------------------------------- 02933 0 Real 3.14159265359 02977 1 Complex (1,2) 02a2c 2 String "hello" or $C 5 hello 029e8 3 Real Array [1 2 3] 029e8 4 Complex Array [(1,0) (2,2)] 02a74 5 List { DUP 3 '3/4' } 02e48 6 Global Name 'PEEK' 02e6d 7 Local Name 't' 02d9d 8 Program << 440 .5 BEEP >> 02ab8 9 Algebraic obj 'SIN(X)' 02a4e 10 Binary Integer # 454432h 02b1e 11 Graphics obj Graphic 4 x 4 GROB 4 4 70607050 02afc 12 Tagged obj root1: 2.6 :root1: 2.6 02ada 13 Unit obj 1_lyr 1_lyr 02e92 14 XLIB name XLIB 2 261 none 02a96 15 Directory DIR Avog 6.02E23 END 02b40 16 Library Library none 02b62 17 Backup obj Backup Object none 02e92 18 Function SIN 02e92 19 Command SWAP 02911 20 Address <28FCh> none 02955 21 Long Real Long Real none 0299d 22 Long Complex Long Complex none 02a0a 23 Linked Array Linked Array none 029bf 24 Character Character none 02dcc 25 Code Code none 02b88 26 Library Data Library Data none other 27 External External none * * * * * * Memory Layout ============= 00000-0FFFF ROM (and registers for the display controller, I/O, and timers) 10000-6FFFF ROM 70000-7FFFF User/Display RAM (overlaid on Font/Strings ROM) 80000-BFFFF 128k for plug-in C0000-FFFFF 128k for plug-in F0000-FFFFF User/Display RAM (when 70000-7FFFF is used for Font/Strings ROM) Memory Scanner ============== There is a built-in memory scan mode that lets you examine and modify memory. This is a convenient way to enter machine code programs into the calculator, to examine memory, and to download memory to a PC via the serial cable. In the key descriptions below, I have referred to several of the keys by their orange labels because the title on the key is a non-ascii symbol. None of these keys should be orange shifted, however. Back up your calculator if necessary. To get into the memory scanner, press [ON][D] together, then [DROP]. You are now in memory scan mode. Following is a list of keys and the functions they perform in scan mode. Most keys will repeat if held down for a moment. All numbers are in hex. [DROP] refresh [LIBRARY] increment by 1000 [REVIEW] decrement by 1000 [/] decrement by 100 [*] increment by 100 [-] decrement by 1 [+] increment by 1 [ENTER] goto address 00100 (?display controller?) [+/-] goto address F000A [1/X] goto address F0A8C or F1210 (display, see below) [EEX] goto address 80000 (?port 1?) [DEL] goto address C0000 (?port 2?) [0]-[F] enter corresponding nibble at address, increment by 1 [.] transmit 16 nibbles to IR and serial, increment by 10 [SPC] dump 1000h memory locations to the serial port (9600 baud) [EVAL] execute at address When you first press [DROP] to enter scan mode, the address is 705D9. Pressing [EVAL] at this address displays: Version HP-48A Copyright HP 1989. The most interesting thing about scan mode is that the memory layout is different than in normal operation. The 32k of user/display RAM is moved from 70000 to F0000 so that you can see the ROM that is normally hidden underneath. In normal operation, the address space at 70000 is shared between this ROM and display RAM. The hidden ROM is used for code and data related to I/O, such as strings and font bitmaps, as well as for diagnostic functions, such as the self tests and scan mode. In normal operation, whenever you need access to the hidden ROM, you have to perform some magic to switch the address space. This must be done in the few cycles between display refresh. F0A8C and F1210 are the addresses of the second line of the bitmap, depending on whether you were looking at the stack or plot displays when you entered scan mode. If you press one of the keys [0]-[F] after pressing [1/X], you can see the effect of writing each nibble into the display bitmap. You can draw on the display this way. * * * * * * The first variable in the HOME directory is stored ending at #7FFFAh, unlike the HP28, where this variable ended at #CFFFF. Address #7FFFAh appears at FFFFA in the memory scanner. I believe that coma mode is entered with [ON][SPC]. When you press on, much of the calculator will have been reinitialized. One undocumented command is WSLOG, which gives you a log of warm starts. I cannot find any command strings with my FIND program. They are most probably stored in the hidden ROM. * * * * * * Easy Machine Code: PEEK and POKE ================================ The obvious way to enter machine code is with scan mode. You don't need to waste time with hex string converters and other silliness. Store the following PEEK program template in the first variable of the HOME directory. << RCWS SWAP 64 STWS #0h OR SWAP STWS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" >> HOME 'PEEK' DUP PURGE STO Now go into scan mode and find the start of the string object: [ON][D], [DROP], [ENTER], [/], hold down [-] until you get to FFFB3. Now change the object type (C2A20) to CCD20 Note that the length is 93000 -> 39 hex = 57 decimal = 26*2 + 5. Move forward to address FFFBD using the [+] key, and enter the machine code into the string. Remember, don't type past FFFF0. 13210314313016914613615671301691547113132142164808C0 Press [ON][C] together to get back to the calculator. You can now checksum PEEK with the BYTES command. The result should be #8568h. This is a binary checksum, so it includes the contents of the Code object, and is independent of display modes. Store the following POKE program template in the first variable of the HOME directory. << SWAP OVER #0h AND OR SWAP "123456789 123456789 123456789 123456789 123" >> HOME 'POKE' DUP PURGE STO Go into scan mode, change type of the string to a Code object as above, and enter the machine code into the string. This string is longer, so you have to go back further to get to the beginning. The machine code still ends at the same address. Be sure you understand the format of string and code objects so that you don't make a fatal mistake. 13210314317414717413416414613618513680D0164 1561E71301691421301541113132142E720164808C0 Press [ON][C] together to get back to the calculator. You can now checksum POKE with the BYTES command. The result should be #725D. * * * * * * Mini RAM Map ============ The address of the end of the stack, normally stored in register D1, is saved at #70579. To examine the stack, first go to F0579 in scan mode: [1/X], [/] 5 times, [-] 19 times The address of the end of the stack is displayed in reverse. If your display says F0579:9F8E7309E7... then the stack starts at 7E903 and ends at 7E8F9. There are obviously two objects on the stack. By moving to FE8F9, you can see the stack itself, and the two addresses it contains. Here is a list of interesting locations (the initial 7 is mapped to an F in scan mode): Real Address Description #704EAh key buffer #70579h top (end) of stack #7057Eh bottom (start) of stack #70583h ?? local variables ?? #70588h ?? internal loop ?? #7058Dh ?? menu keys ?? #70592h HOME directory #70597h end of HOME directory (7FFFB) (points to five 0 nibbles, probably used for ATTACH) #7059Ch current directory #70713h graphic obj used for composing lines of the stack. There is just enough memory reserved for a 19 character bitmap. #70844h graphic obj used for menu display: 8 by 131 #70968h graphic obj used for the rest of the screen: 56 by 131 #710ECh graphic obj used for plot display: variable size The questionable values are inferred from the HP-28 RAM map by Dave Kaffine. There are obviously many similarities. You can use the real addresses at #7xxxxh employing PEEK. * * * * * * Keyboard Buffer and Scan Codes ============================== The keyboard buffer works just like in the 28. The scan codes run in sequence: #01h for A, #02h for B, ..., #30h for SPC, #31h for +. There are 49 keys and the scan codes run from 1 to 49 (#01h to #31h), with four exceptions. The key codes #1Eh, #23h, #28h, and #2Dh are not used. The first three are replaced with #80h for AlphaShift, #40 for LeftShift, and #C0 for RightShift, and the ON/ATTN/CONT/OFF key has no scan code. When a key is pressed, the interrupt handler puts the scan code into the next position of the keyboard buffer, except for the ON key which gets special treatment. I assume that the shift values can be OR'd with the scan value to get more compact key codes. Obviously one can not apply mutliple shifts to the same character this way. * * * * * * Command List and SYSEVAL Map ============================ Here are all the commands in the HP48 with their command number and address. This list serves as a map for navigating through the ROM. Each address is the beginning of an RPL routine. Note how short these routines are. The 48 has been set up so that command addresses never change. Disassembling the commands will lead the way to the underlying RPL routines stored elsewhere in ROM and eventually a complete SYSEVAL map. On the 48, for the first time, programming with these faster SYSEVAL addresses is easy (it can be done on the PC and downloaded). Of course, that defeats the whole purpose of having the standardized ROM addresses below. A utility for speeding up user programs could automatically expand commands into the underlying RPL. Once a program is tested, some of the built in error checking code can be circumvented. This is kind of like a compiler since your source would be user code. Addr XLIB # Name Addr XLIB # Name Addr XLIB # Name ---------------------- ---------------------- ---------------------- 1957B 000002 ASR 1C3CF 089002 GRAD 1FC7F 116002 DUPN 1959B 001002 RL 1C3EA 08A002 FIX 1FC9A 117002 PICK 195BB 002002 RLB 1C41E 08B002 SCI 1FCB5 118002 ROLL 195DB 003002 RR 1C452 08C002 ENG 1FCD0 119002 ROLLD 195FB 004002 RRB 1C486 08D002 STD 1FCEB 11A002 CLEAR 1961B 005002 SL 1C4A1 08E002 FS?C 1FD0B 11B002 STOsigma 1963B 006002 SLB 1C520 08F002 FC?C 1FD2B 11C002 CLsigma 1965B 007002 SR 1C559 090002 BIN 1FD46 11D002 RCLsigma 1967B 008002 SRB 1C574 091002 DEC 1FD61 11E002 sigma+ 1969B 009002 R->B 1C58F 092002 HEX 1FD8B 11F002 sigma- 196BB 00A002 B->R 1C5AA 093002 OCT 1FDA6 120002 Nsigma 196DB 00B002 CONVERT 1C5C5 094002 STWS 1FDC1 121002 CORR 1971B 00C002 UVAL 1C5FE 095002 RCWS 1FDDC 122002 COV 1974F 00D002 UNIT 1C619 096002 RCLF 1FDF7 123002 sigmaX 19771 00E002 UBASE 1C67F 097002 STOF 1FE12 124002 sigmaY 197A5 00F002 UFACT 1C78C 098002 ->LIST 1FE2D 125002 sigmaX^2 197F7 010002 TIME 1C79E 099002 R->C 1FE48 126002 sigmaY^2 19812 011002 DATE 1C7CA 09A002 RE 1FE63 127002 sigmaX*Y 1982D 012002 TICKS 1C819 09B002 IM 1FE7E 128002 MAXsigma 19848 013002 WSLOG 1C85C 09C002 SUB 1FE99 129002 MEAN 19863 014002 ACKALL 1C8EA 09D002 REPL 1FEB4 12A002 MINsigma 1987E 015002 ACK 1C95A 09E002 LIST-> 1FECF 12B002 SDEV 1989E 016002 ->DATE 1C98E 09F002 C->R 1FEEA 12C002 TOT 198BE 017002 ->TIME 1C9B8 0A0002 SIZE 1FF05 12D002 VAR 198DE 018002 CLKADJ 1CAB4 0A1002 POS 1FF20 12E002 LR 198FE 019002 STOALRM 1CB0B 0A2002 ->STR 1FF7A 12F002 PREDV 19928 01A002 RCLALRM 1CB26 0A3002 STR-> 1FF9A 130002 PREDY 19948 01B002 FNDALRM 1CB46 0A4002 NUM 1FFBA 131002 PREDX 19972 01C002 DELALRM 1CB66 0A5002 CHR 1FFDA 132002 XCOL 19992 01D002 TSTR 1CB86 0A6002 TYPE 1FFFA 133002 YCOL 199B2 01E002 DDAYS 1CE28 0A7002 VTYPE 2001A 134002 UTPC 199D2 01F002 DATE+ 1CEE3 0A8002 EQ-> 2003A 135002 UTPN 1A105 020002 CRDIR 1CF7B 0A9002 OBJ-> 2005A 136002 UTPF 1A125 021002 PATH 1D009 0AA002 ->ARRAY 2007A 137002 UTPT 1A140 022002 HOME 1D092 0AB002 ARRY-> 2009A 138002 COLsigma 1A15B 023002 UPDIR 1D0DE 0AC002 RDM 200C4 139002 SCLsigma 1A194 024002 VARS 1D186 0AD002 CON 200F3 13A002 sigmaLINE 1A1AF 025002 TVARS 1D2DC 0AE002 IDN 2010E 13B003 BINS 1A1D9 026002 BYTES 1D392 0AF002 TRN 20133 13C002 BARPLOT 1A2BC 027002 NEWOB 1D407 0B0002 PUT 20167 13D002 HISTPLT 1A303 028002 KILL 1D5DF 0B1002 PUTI 2018C 13E002 SCTRPLT 1A31E 029002 OFF 1D7C6 0B2002 GET 201B1 13F002 LINFIT 1A339 02A002 DOERR 1D8C7 0B3002 GETI 201D6 140002 LOGFIT 1A36D 02B002 ERR0 1DD06 0B4002 V-> 201FB 141002 EXPFIT 1A388 02C002 ERRN 1DE66 0B5002 ->V2 20220 142002 PWRFIT 1A3A3 02D002 ERRM 1DEC2 0B6002 ->V3 2025E 143002 BESTFIT 1A3BE 02E002 EVAL 1E04A 0B7002 INDEP 202CE 144002 SINV 1A3FE 02F002 IFTE 1E07E 0B8002 PMIN 2034D 145002 SNEG 1A4C0 030002 IFT 1E09E 0B9002 PMAX 203CC 146002 SCONJ 1A52E 031002 SYSEVAL 1E0BE 0BA002 AXES 2044B 147002 STO+ 1A584 032002 DISP 1E0E8 0BB002 CENTR 20538 148002 STO- 1A5A4 033002 FREEZE 1E126 0BC002 RES 2060C 149002 STO/ 1A5C4 034002 BEEP 1E150 0BD002 *H 20753 14A002 STO* 1A5E4 035002 ->NUM 1E170 0BE002 *W 208F4 14B002 INCR 1A604 036002 LASTARG 1E190 0BF002 DRAW 209AA 14C002 DECR 1A71F 037002 WAIT 1E1AB 0C0002 AUTO 20A15 14D002 COLCT 1A858 038002 CLLCD 1E1C6 0C1002 DRAX 20A49 14E002 EXPAN 1A873 039002 KEY 1E1E1 0C2002 SCALE 20A7D 14F002 RULES 1A8BB 03A002 CONT 1E201 0C3002 PDIM 20A93 150002 ISOL 1A8D8 03B002 = 1E22B 0C4002 DEPND 20AB3 151002 QUAD 1A995 03C002 NEG 1E25F 0C5002 ERASE 20AD3 152002 SHOW 1AA1F 03D002 ABS 1E27A 0C6002 PX->C 20B20 153002 TAYLR 1AA6E 03E002 CONJ 1E29A 0C7002 C->PX 20B40 154002 RCL 1AABD 03F002 pi 1E2BA 0C8002 GRAPH 20CCD 155002 STO 1AADF 040002 MAXR 1E2D5 0C9002 LABEL 20D65 156002 DEFINE 1AB01 041002 MINR 1E2F0 0CA002 PVIEW 20EFE 157002 PURGE 1AB23 042002 e 1E31A 0CB002 PIXON 20FAA 158002 MEM 1AB45 043002 i 1E344 0CC002 PIXOFF 20FD9 159002 ORDER 1AB67 044002 + 1E36E 0CD002 PIX? 210FC 15A002 CLVAR 1ACD7 045002 + 1E398 0CE002 LINE 2115D 15B002 TMENU 1AD09 046002 - 1E3C2 0CF002 TLINE 21196 15C002 MENU 1ADEE 047002 * 1E3EC 0D0002 BOX 211E1 15D002 RCLMENU 1AF05 048002 / 1E416 0D1002 BLANK 211FC 15E002 PVARS 1B02D 049002 ^ 1E436 0D2002 PICT 2123A 15F002 PGDIR 1B185 04A002 XROOT 1E456 0D3002 GOR 2125A 160002 ARCHIVE 1B1C4 04B002 XROOT 1E4E4 0D4002 GXOR 2133C 161002 RESTORE 1B278 04C002 INV 1E572 0D5002 LCD-> 2137F 162003 MERGE 1B2DB 04D002 ARG 1E58D 0D6002 ->LCD 213D1 163002 FREE 1B32A 04E002 sigmaN 1E5AD 0D7002 ->GROB 2142D 164002 LIBS 1B374 04F002 sqrt 1E5D2 0D8002 ARC 21448 165002 ATTACH 1B426 050002 SQ 1E606 0D9002 TEXT 2147C 166002 DETACH 1B4AC 051002 SIN 1E621 0DA002 XRNG 21E75 167002 XMIT 1B505 052002 COS 1E641 0DB002 YRNG 21E95 168002 SRECV 1B55E 053002 TAN 1E661 0DC002 FUNCTN 21EB5 169002 OPENIO 1B5B7 054002 SINH 1E681 0DD002 CONIC 21ED5 16A002 CLOSEIO 1B606 055002 COSH 1E6A1 0DE002 POLAR 21EF0 16B002 SEND 1B655 056002 TANH 1E6C1 0DF002 PARMTRC 21F24 16C002 KGET 1B6A4 057002 ASIN 1E6E1 0E0002 TRUTH 21F62 16D002 RECN 1B72F 058002 ACOS 1E701 0E1002 SCATTER 21F96 16E002 RECV 1B79C 059002 ATAN 1E721 0E2002 HISTGRM 21FB6 16F002 FINISH 1B7EB 05A002 ASINH 1E741 0E3002 BAR 21FD1 170002 SERVER 1B830 05B002 ACOSH 1E761 0E4002 SAME 21FEC 171002 CKSM 1B8A2 05C002 ATANH 1E783 0E5002 AND 2200C 172002 BAUD 1B905 05D002 EXP 1E809 0E6002 OR 2202C 173002 PARITY 1B94F 05E002 LN 1E88F 0E7002 NOT 2204C 174002 TRANSIO 1B9C6 05F002 LOG 1E8F6 0E8002 XOR 2206C 175002 KERRM 1BA3D 060002 ALOG 1E972 0E9002 == 22087 176002 BUFLEN 1BA8C 061002 LNP1 1EA9D 0EA002 != 220A2 177002 STIME 1BAC2 062002 EXPM 1EBBE 0EB002 < 220C2 178002 SBRK 1BB02 063002 ! 1EC5D 0EC002 > 220DD 179002 PKT 1BB41 064002 FACT 1ECFC 0ED002 <= 224CA 17A002 INPUT 1BB6D 065002 IP 1ED9B 0EE002 >= 224F4 17B002 ASN 1BBA3 066002 FP 1EE38 0EF002 OLDPRT 22514 17C002 STOKEYS 1BBD9 067002 FLOOR 1EE53 0F0002 PR1 22548 17D002 DELKEYS 1BC0F 068002 CEIL 1EE6E 0F1002 PRSTC 22586 17E002 RCLKEYS 1BC45 069002 XPON 1EE89 0F2002 PRST 225BE 17F002 ->TAG 1BC71 06A002 MAX 1EEA4 0F3002 CR 22633 180002 DTAG 1BCE3 06B002 MIN 1EEBF 0F4002 PRVAR 22EC3 000700 IF 1BD55 06C002 RND 1EF43 0F5002 DELAY 22EFA 001700 THEN 1BDD1 06D002 TRNC 1EF63 0F6002 PRLCD 22FB5 002700 ELSE 1BE4D 06E002 MOD 1EF7E 0F7002 delta 22FD5 003700 END 1BE9C 06F002 MANT 1EFCC 0F8002 delta 22FEB 004700 -> 1BEC8 070002 D->R 1F133 0F9002 RCEQ 23033 005700 WHILE 1BEF4 071002 R->D 1F14E 0FA002 STEQ 2305D 006700 REPEAT 1BF1E 072002 ->HMS 1F16E 0FB002 ROOT 230C3 007700 DO 1BF3E 073002 HMS-> 1F1D4 0FC002 integral 230ED 008700 UNTIL 1BF5E 074002 HMS+ 1F21D 0FD002 integral 23103 009700 START 1BF7E 075002 HMS- 1F2C9 0FE002 sigma 231A0 00A700 FOR 1BF9E 076002 RNRM 1F354 0FF002 | 2324C 00B700 NEXT 1BFBE 077002 CNRM 1F3ED 100002 | 23380 00C700 STEP 1BFDE 078002 DET 1F500 101002 QUOTE 233DF 00D700 IFERR 1BFFE 079002 DOT 1F55D 102002 APPLY 23472 00E700 HALT 1C007 07D002 %T 1F9C4 107002 ->Q 2349C 00F700 1C01E 07A002 CROSS 1F9E9 108002 ->Qpi 234C1 010700 -> 1C03E 07B002 RSD 1FA59 109002 ^MATCH 235FE 011700 >> 1C060 07C002 % 1FA8D 10A002 vMATCH 2361E 012700 << 1C149 07E002 %CH 1FAEB 10B002 _ 23639 013700 >> 1C1B9 07F002 RAND 1FB5D 10C002 RATIO 23654 014700 ' 1C1D4 080002 RDZ 1FB87 10D002 DUP 23679 015700 ' 1C1F6 081002 COMB 1FBA2 10E002 DUP2 23694 016700 END 1C236 082002 PERM 1FBBD 10F002 SWAP 236B9 017700 END 1C274 083002 SF 1FBD8 110002 DROP 2371F 018700 THEN 1C2D5 084002 CF 1FBF3 111002 DROP2 2378D 019700 CASE 1C313 085002 FS? 1FC0E 112002 ROT 237A8 01A700 THEN 1C360 086002 FC? 1FC29 113002 OVER 23813 01B700 DIR 1C399 087002 DEG 1FC44 114002 DEPTH 23824 01C700 PROMPT 1C3B4 088002 RAD 1FC64 115002 DROPN Alonzo Gariepy alonzo@microsoft