HP Forums
ASM Programming with HP50g - Printable Version

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Calculators (and very old HP Computers) (/forum-3.html)
+--- Forum: General Forum (/forum-4.html)
+--- Thread: ASM Programming with HP50g (/thread-16008.html)



ASM Programming with HP50g - Helge P - 12-04-2020 01:18 PM

Hello everybody.
I've been interested in HP pocket calculators for several years. I started with an HP48GX. With that I was able to acquire a bit of Saturn assembler basics.
Then a long time ago I bought an HP50G to program some ARM assembler. For many years I didn't get around to doing anything with it.
Now I have a little more time and am currently looking for information on the Internet and collecting information on how the HP50g works internally. I also don't have that much experience with ARM assembler programming.
I get the Samsung's s3c2410 book and i collected some scattered information.
I tried the basic program that contains the embedded ARM code and also the sample program from the HP50g Advanced User Manual. Now I don't really know what to do next. I wanted to learn more about how the ARM parts work in the HP50.
I then tried to use the binary file from an emulator project to find out more what the computer would do, for example, when it was restarted completely. After a long search on the Internet I found a simple program that can load the binary file and then disassembled into ARM code, which you can then run step by step. You can watch the process registers.
Here I already have the first question. I'm not sure at which address the processor of the HP50g starts after a complete restart. I accepted the address zero, but I don't know exactly. I also searched the Internet for it and found nothing.
Then I found something about JTAG in the s3c2410 manual and read a bit about it, that you can use it to debug directly on a processor. Is that also possible with the HP50g? And if so, what do you need for it? Is this possible via USB or do you have to open the device? And what software can you use for it.
Or is it perhaps also possible to compile code with a development environment and upload it directly to the HP and debug it, like for example with an ESP32 or an Android device?
Is it somehow possible with the internal development tools to debug an ARM program, i.e. to go through it step by step and view the processor registers? I haven't found anything about it, just the possibility that the assembler can generate debug information. But there is no more detailed information about the format in which and what exactly you can do with it.
I would like to move on to ARM assembler with the HP50G. I like the computer a lot because it has an ARM processor and, unlike an ESP32, for example, it already has a keyboard and LCD display that can also be read in sunlight. And it can run on batteries for a long time.
Maybe there is someone here who can answer a few questions for me.
And maybe a little further can help to get more information about the HP50g internally.


RE: ASM Programming with HP50g - hth - 12-04-2020 07:49 PM

Not that it answers your questions, but just some random notes.

With JTAG you connect to some debug port on the chip, there are different connectors and it may or may not be exposed on a production device.

On the computer side, you will need some cross development tools. They are mainly for C/C++ and connects to the JTAG device, usually with USB. Many debuggers can do assembly level debugging, allowing you to see registers and stepping in assembly source code, but that is not always the case, or the experience may be somewhat less than ideal in the user interface. As I said, they are usually targeted to C/C++ level debugging.

The HP50G is not what I would think of as my first choice when it comes to playing around with at this level. (I base this on my experiences with the HP48, the HP50G may be a different story.)

For example, you can get the Pinetime smart watch for small money if you want to play with ARM and do something fun. You could go to the Swissmicros DM43 if you want to do some new development on ARM.

If you want to mess around with assembly level programming on an HP, the HP41 could be an alternative as we have so much in depth information on it. I develop at assembly level with the HP41 and can step around and see what is going on internally. Basically all information is around, fully documented source code and several tools to choose from.


RE: ASM Programming with HP50g - 3298 - 12-05-2020 12:24 PM

For the 50g, I'd suggest going with a purely software-based solution for your initial experiments. x49gp emulates the 50g at the ARM level (unlike Emu48, which only runs Saturn code), so you can just connect gdb to it (or a visual debugger with gdb backend, if you want) and start from there. Emulation of the CPU's peripherals isn't perfect, but the essentials work well enough; the ARM code it's running is an exact replica of what's found on the real hardware. All you need is a non-Windows computer to run this software on. From there, you can peek, poke, disassemble, single-step, set breakpoints, and all the usual stuff gdb allows you to do.

By the way, ARM processors start from address 0 on boot. On the 50g, the flash memory is mapped into that section of the address space. The first 16KiB are a boot sector, the upgradeable firmware starts after that. (x49gp creates a raw flash image on first launch, if you want to take a look without going through gdb.) RAM is mapped ... somewhere else, I forget where exactly. I think there's a text file in the x49gp repo that has more details about the memory map; failing that, its source code should know.

If you are interested in peripherals, things get a bit more fuzzy because x49gp is built on a bit of guesswork, and in some places simply incomplete. The best way to proceed would likely be to write small programs for experiments with a peripheral. And if you do that, feel free to submit patches or documentation to x49gp so we can improve it; any help is welcome.


RE: ASM Programming with HP50g - Helge P - 12-07-2020 10:38 AM

Thanks for the answers.
I actually have a copy of x49gp on my computer. But it's a windows computer. I have little experience with Linux or similar systems. And just with the source code alone, I didn't get very much further.
I have never used the gdb either. So far I've only worked with Visual Studio and a little with Eclipse (Java Android).
But with another program called "ARMu" I was able to find out or adjust some things, as it is described on the page http://lebonpoint.chez-alice.fr/hp49gp/reverse.htm.
I copied a binary file that corresponds to the memory of the HP50G. With ARMu I can load the binary file and then step through it. I will first take a look at it and try to understand what is happening
I had previously tried to do just that with some other programs, e.g. from the Lauterbach site, or with ARM development tools, but I couldn't do it with that.


RE: ASM Programming with HP50g - 3298 - 12-08-2020 02:38 PM

Oh, dear ... Windows only? You see, I've become a happy Linux-only person a few years ago, sooo... well, I won't tell you to switch, but things that I find natural, like working out of a terminal, compiling software on my own, viewing man-pages, etc., might be foreign concepts to you. Conversely, I'm not quite up to date on Windows stuff. I'll do my best to tell you how you can get started regardless.

Full disclosure: I've made some contributions to x49gp, so I may be a bit biased. However, as far as I can tell it would be the best tool available for your explorations - based on a quick search, this "ARMu" you mentioned seems to be a generic ARM tool without 50g-specific pieces like display and keyboard, so it would probably only get you so far. By all means, try it anyway - though since I don't know anything about it, I wouldn't be able to help you much with that tool. With x49gp, on the other hand, I have enough knowledge to troubleshoot and probably fix issues if any come up.

I suspect you are a little scared by the prospect of switching your entire operating system (who wouldn't be!), but that's not actually necessary. (I did try to make x49gp run on Windows once, but I was only able to confirm that it doesn't even compile in MinGW, and in Cygwin it compiles fine but crashes on startup somewhere deep inside the QEmu code that does the actual ARM emulation for x49gp. I just gave up after that.) Let's get you a virtual Linux environment inside your Windows instead. WSL2 supposedly has a beta with experimental support for graphical applications, but a full VM is probably your best bet right now. You'll need software to host the VM (Microsoft Virtual PC, Oracle VirtualBox, ... whatever floats your boat), and a Linux distro. I tend to recommend Ubuntu for newcomers: stable and well-supported by software devs, very user-friendly, and because it is so popular, there are plenty of answered questions out there in case of trouble. The exact steps to set this all up depend on your choices - but if you are experienced enough with a computer to try dealing with ASM, you should be able to find your way through.

Once you have your Linux desktop up and running, you'll want to open a terminal. Several of the following steps can be done with graphical applications too, but how these applications work can be very different, and a handful of steps require the terminal anyway, so let's keep it simple and do everything in it.
First, you'll need to install a few pieces of software so you can compile x49gp. Many Linux distros already have them installed, but there are some which don't, so let's just make sure they are there. The command to install a package on Ubuntu is 'sudo apt-get install name-of-the-software', and the programs we need are: git, make, gcc. The "sudo" at the start of the line means "do this with system administrator privileges", and it will accordingly ask you to type the system administrator password - that's perfectly normal, it should be the password of the user you set up during installation of the Linux distro.

Then, let's get x49gp and compile it. Right now, Claudio's repository on GitHub is the one with all the bells and whistles, so issue the command "git clone https://github.com/claudiobsd/x49gp/", then change into the directory created by that operation with "cd x49gp", and finally tell the computer to compile it all with "make". It'll take a moment ... and then you have a fully operational copy of x49gp at your fingertips. You can either just run it from that directory, or you can install it system-wide with "sudo make install". If you choose the latter, you'll be able to refer to it as "x49gp" from anywhere; if you choose the former, you'll always have to specify the path to it (even if it's the same directory you're already in). Be careful - in Linux the path separator is a forward slash, not a backward slash as in Windows (though I think Windows can now deal with forward slashes too), so the command to run it from the current directory would be "./x49gp". I recommend installing it - that also gives you a shortcut in your application menu, and a man-page which you'll be able to view with "man x49gp" (written by yours truly, by the way). Reading that might be a good idea, actually, because then you'll better understand the debug options you'll use in a moment. It also gives some information about where x49gp's persistent data ends up, which may be useful to you - it includes binary images of RAM and flash memory, for instance.

The parameter to launch x49gp in debug mode is "-d", which makes the full command "x49gp -d". However, it'll appear to get stuck, because it's waiting for a connection from the debugger. Also, once the debugger is hooked up to it and tells x49gp to execute an instruction, it'll continue wherever it was stopped during its last run. That won't be a problem the first time because it'll prompt you to select a firmware and then boot up from 0, but on subsequent runs you would be ... probably somewhere inside the Saturn emulator embedded in the stock firmware. You can force it to reboot by adding the "-r" parameter to the command line, though.

With x49gp waiting for a connection, let's run the debugger in a second terminal. Oh wait, it's not installed yet. Well, that's easy to fix, "sudo apt-get install binutils-arm-none-eabi". Once installed, run "arm-none-eabi-gdb". Normally you would pass the name of a program as parameter, and the debugger would read debug info from it, but for this case we don't have access to such luxury.
GDB will offer its own command prompt, allowing you to control what happens with program execution. The first command we need here is "target remote :1234". You can also insert "localhost" before the colon, but that's implicit. What this causes GDB to do is to connect to TCP port 1234 (which is x49gp's default debugging port) and route all program-controlling requests through that connection. And yes, this is real TCP - x49gp and GDB could run on different computers, though that's usually not so useful. There might be a case for using this mechanism to run GDB outside your Linux VM, but getting the ARM version of it for Windows is probably more trouble than it's worth. You might be tempted to do so if you could then hook it up to Eclipse ... but like any IDE that one is made for debugging a program whose source is loaded in it, not for poking around unknown code. Let's not bother with that then.

Okay, you now have x49gp paused at the start of its boot sequence, and GDB connected to it. Now you can start investigating whatever you want. The most useful commands for that would be:
- "stepi" executes a single instruction. There is a variant without the "i" at the end, but that tries to run a whole line of source code ... which needs the debug info we don't have. Like many commands, this one has an abbreviation: "si".
- "nexti" is similar, but if the instruction is a subroutine call, it'll step over it, i.e. run until the subroutine finishes. Abbreviated as "ni", and it also has a useless-to-us whole-line-of-source variant without the "i" at the end.
- "info registers" shows you all the processor registers. Can be abbreviated as "i r".
- "print expression" calculates an expression and shows the result. The syntax for the expression is very C-like with typecasting, pointer arithmetic etc. For instance, you could write "print *((int *) $r0)" to have the register r0 interpreted as a pointer to integers, and have GDB tell you the value of the integer it points to. You'll also notice that the result is given back with "$number = " in front of it - that's a hint that you can reference these results with the corresponding number and a dollar sign in front of it in subsequent expressions. The "print" command can also be abbreviated as "p".
- "disassemble start, end" disassembles a portion of code between two addresses. Abbreviate as "disas".
- "break address" sets a breakpoint. Abbreviate as "b".
- "continue" runs until it hits a breakpoint. Abbreviate as "c". If you don't have a breakpoint, it'll just keep running, which in our case means you'll soon end up inside the Saturn emulator. Hitting Ctrl-C while it's running will also interrupt execution, but you likely can't do that fast enough to correct mistakes.
- When you're done, "quit" will terminate GDB. x49gp will automatically run on its own after that, but if you queue up a Ctrl-C in its terminal before exiting GDB, it's going to terminate too. Otherwise, x49gp can be closed from the menu which appears on a right-click on the emulated display, but x49gp's simplistic single-threaded design keeps the UI from responding to the right-click while it's waiting on GDB commands.
For the rest, I'll just refer to the "help" command, which tells you what's up.

There you go, from zero to ASM debugging with x49gp. Wink Feel free to keep asking questions, there are enough knowledgeable people around here to help you out.


RE: ASM Programming with HP50g - Helge P - 12-10-2020 09:13 PM

Oh wow. Thank you for your detailed description. I almost have to switch to Linux.
I think I'll try it out with a VM and Ubuntu.
I will soon have a few days of vacation and I'll test it out. :-)


RE: ASM Programming with HP50g - Eric Rechlin - 12-12-2020 03:09 PM

Windows 10 has WSL which gives you a full Ubuntu environment. I've found it to work very well for my purposes; maybe it will work for you too. I haven't tried running any graphical apps with it, though, but I know others have had success.


RE: ASM Programming with HP50g - ijabbott - 12-13-2020 12:38 PM

(12-12-2020 03:09 PM)Eric Rechlin Wrote:  Windows 10 has WSL which gives you a full Ubuntu environment. I've found it to work very well for my purposes; maybe it will work for you too. I haven't tried running any graphical apps with it, though, but I know others have had success.

Currently, they can be run in a virtual X display viewed by a Remote Desktop Protocol (RDP) client or Virtual Network Computing (VNC) client, but it involves some port forwarding.

Microsoft are working on a Wayland compositor with built-in RDP that integrates Linux application windows into the Windows desktop. (Wayland is a sort of replacement for the 30-plus-year-old X11 Window System.)


RE: ASM Programming with HP50g - Helge P - 05-09-2021 02:55 PM

Hallo
It's been some time since my last post. I got a little more experience in ARM assembler programming in administration.
I use the built-in assembler MASD to translate small programs.
Here I have the problem that the LDR command does not work with a label. Here, for example, I would like to load the start address of the text "Hello World" into register R10 with "LDR R10, TEXT". But when I start the program, it crashes immediately

SKUBL{
*START
!ARM
STMDB SP! {R4 R5 R6 R7 R8 LP}

MOV R1, #$8
MOV R2, #$8
MOV R3, #$0
MOV R4, #$50

BL INTOFF
BL CLEARSCREEN
BL PrintText
BL WaitForLS
BL INTON
B ENDE

*PrintText
STMDB SP!, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, LR}
LDR R10, TEXT
*NextChar
BL PrintChar
ADD R10, R10, #$2
LDRB R4, [R10]
CMP R4, #$00
BNE NextChar
LDMIA SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, PC}

*TEXT
¢Hello World ¢

In the meantime I have also found out how to debug the HP50g with Jtag and OpenOCD from the outside. Now I can set a breakpoint and start my compiled program. It then stops at the breakpoint and I can then run the priogram step by step, view registers and disassemble the memory contents.
This shows that the MASD compiler translates something else from the "LDR R10, TEXT" command. (SUB r15, r3, r4 LSL r0)

Here is a disassembled part of the memory content via JTAG.
The line marked in red is what MASD generated

[Image: Speicherauszug.jpg]

Now my question is now. Is this is a error in MASD or have I made a mistake in the Systax, for example?


RE: ASM Programming with HP50g - 3298 - 05-09-2021 04:12 PM

Looks like both, actually. The resulting instruction seems like a bug in MASD, but what you're trying to do will not work even without that bug - the compiler cannot know at what address TEXT will end up, so you'll have to write position-independent code. That usually means relative addressing, i.e. adding the program counter and a difference between labels together, instead of loading a constant that will go invalid when the code and its attached data is moved somewhere else.
If you wonder why branching to labels does work, internally those are relative already. If you look closely at the hex-encoded instructions, you can actually spot it.


RE: ASM Programming with HP50g - toml_12953 - 05-09-2021 04:58 PM

(12-10-2020 09:13 PM)Helge P Wrote:  Oh wow. Thank you for your detailed description. I almost have to switch to Linux.
I think I'll try it out with a VM and Ubuntu.
I will soon have a few days of vacation and I'll test it out. :-)

If you run Windows 10, you can use WSL2 to run Linux software in a window without having to load an entire emulator although VirualBox does work perfectly as well.


RE: ASM Programming with HP50g - Helge P - 05-09-2021 05:04 PM

Oh, okay.
I understand, but I had thought that the compiler would also calculate the relative addresses for the LDR command.
The MASD documentation describes that a label can be used for LDR:

LDR{cond} Rd, Label Rd:= data at label. The label address is calculated relative to the PC. This does not work with constants.

Or is that a constant at this address?


RE: ASM Programming with HP50g - 3298 - 05-09-2021 05:51 PM

I have to admit, I didn't write ARM assembly code in MASD for quite a while, and didn't check the documentation. Apparently it's doing a bit more than I gave it credit for (or claiming to, anyway), because as simple as it is compared to many modern compilers and assemblers, I just assumed it wouldn't convert instructions into other instructions to make them work at all.
It's not a constant in MASD terms, that's some stuff around the DCCP macro. So just a frustrating MASD bug.

I just had another idea what may be causing it though: since this is clearly just an excerpt from your program, could it be that there's enough stuff inbetween for the TEXT label to be out of range from the LDR instruction? A lack of range validation would be a bug, to be sure, but it would at least explain why MASD is producing garbage.
Or maybe your program gets corrupted in some way between compilation and execution.
You could also try using the 50g's builtin tools to look at what MASD spat out, like \->H for a hex dump (mind the endianness) and ARM\-> to disassemble (though the latter is going to need some address calculations from you to make it disassemble the right piece of memory).


RE: ASM Programming with HP50g - Helge P - 05-10-2021 04:59 PM

I had disassemble the programm on the HP50G with skipping the routine that include the wrong compiled command otherwise the calculator will be crashed and I cannot execute the disassemble command.
The result is the same

C0000 STMDB R13 ! { R4 R5 R6 R7 R8 LP }
C0008 MOV R1 $00000008
C0010 MOV R2 $00000008
C0018 MOV R3 $00000000
C0020 MOV R4 $00000050
C0028 BL C0210
C0030 BL C0178
C0038 BL C01D0
C0040 BL C0360
C0048 B C13B0
C0050 STMDB R13 ! { R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 LP }
C0058 SUB PC R3 R4 < R0
C0060 BL C00A8
C0068 ADD R10 R10 $00000002
C0070 LDRB R4 [R10 ]
C0078 CMP R4 $00000000
C0080 BNE C0060
C0088 LDMIA R13 ! { R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 PC }
C0090 $6C6C6548
...

And the distance between the LDA command and the label is only a few instructions. The distance cannot actually be outside the address range.

Because that doesn't work with the label, I use this code instead to get the address into register R10

*PrintText
STMDB SP!, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, LR}
BL TEXT
*NextChar
BL PrintChar
ADD R10, R10, #$2
LDRB R4, [R10]
CMP R4, #$00
BNE NextChar
LDMIA SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, PC}

*TEXT
STMDB SP!, {LR}
MOV R10, PC
LDMIA SP!, {PC}
¢Hello World¢
*NULL
$00

Here I jump to the place of the label and write the address of the PC in register R10 and jump back again. Maybe there is a better way, but it works so far.


RE: ASM Programming with HP50g - 3298 - 05-10-2021 06:24 PM

Hmmm, that's a quite roundabout way of getting the address. How about:
Code:
...
ADD R10, PC, TEXT-HERE
*HERE
...
*TEXT
¢Hello World¢
You might have to put a constant offset into the calculation - if I recall the details of the ARM program counter correctly (ahead of the current instruction by 3 instruction lengths), the offset ought to be -12.
This explicitly relatively-addressing instruction is approximately what the LDR instruction should be converted to without the MASD bug. Hopefully this syntax makes it through unscathed.


RE: ASM Programming with HP50g - Claudio L. - 05-14-2021 02:11 AM

Hello, it's great to see people interested in ARM Assembly.
One option that I didn't see mentioned is to use hpgcc3. You can use embedded assembler within C. And since it's GCC compiling it, you won't get any surprises like MASD.
The debugging works together with x49gp: when you run your C program, right before jumping into main, it will trigger a breakpoint so the Eclipse IDE will stop at main().
You can also look at the HPGCC3 source code to see hardware drivers for the S3C2410.

Oh, and since hpgcc3 has nice exception handlers, it will actually trap your errors and display all registers just as you would expect.


RE: ASM Programming with HP50g - Helge P - 05-19-2021 05:40 PM

That sounds good with the hpgcc3 compiler. I experimented briefly with hpgcc2 a few months ago.
But what I really want is to program in assembler on the HP itself. Without having a computer as an additional device. Unfortunately, this is not possible at the moment, as I do not have a lot of experience in assembler programming and therefore I often have to debug what is happening in there with the help of OpenOCD and Jtag. Certainly the HP50 is not the best way to learn assembly language, but I kind of like it. I would have taken another device, but I haven't found anything that is battery operated, has an ARM processor, a keyboard, a display, and a built-in one ARM assembler.
What would help me would be an ARM debugger on the HP50 itself. As with JAZZ for the Saturn processor. But I still have no idea how something like this could be implemented. Maybe someone can help me and explain how such a debugger could work for the ARM processor on the HP50


RE: ASM Programming with HP50g - TRS80 - 11-16-2023 10:55 AM

Chiming in that I did get this to work on the pre-built Linux Mint appliance, on VirtualBox, running under Win10:

It took a bunch of attempts, and I'm only paraphrasing what I did as it was an iterative process, and I never went back to try from a clean slate.

- I used the code from Github
- I had to install some missing libraries such as zlib.
- I used the instructions on Source Forge to update the makefile.

Then I was able to build and run.


RE: ASM Programming with HP50g - TRS80 - 11-27-2023 11:27 AM

One thing to report with my build: the right-click and menu key does not work. I wanted to try the virtual SD and the right-click in the display does not do anything.


RE: ASM Programming with HP50g - 3298 - 11-27-2023 08:16 PM

That's odd, which GitHub repo did you use? The link I posted in this thread leads to Claudio's, which definitely does have the changes for that. Some other repos are stuck at an older version, though those should also be the ones missing fixes for errors with current compilers, i.e. you should have gotten stuck when attempting to use an outdated version. But you mention some SourceForge instructions ... ?!? something like that shouldn't be necessary.
At the time of posting Claudio's was the best repo to use; right now I'm leaning towards another, https://github.com/gwenhael-le-moine/x49gp/ (by another user interested in keeping x49gp going - the name on this forum is gwh, and he's also offering a renovated fork of x48). The difference between the repos is something the average user is unlikely to care about, some license compliance stuff that only affects compiling, installing, and setup on the first run. Claudio's repo has several commits in that direction, gwh's piles on some more. There's room to improve on this (as usual), but if you arrived at a working calculator, you're already past the effects of these changes. (Interested readers: the discussion leading to the commits is over there.

Alternatively, the problem could be one of the "not holding it right" type: the menu appears when right-clicking on the emulated screen, or when pressing the context menu key, which is commonly located next to the right Ctrl key. Some laptop keyboards unfortunately omit it or make it an Fn-combo function of another key.

---

For what it's worth, if I remember correctly the SD emulation itself didn't change since before x49gp arrived on GitHub, I merely made it more accessible.
In older versions it required fiddling with the config: in the section
Code:
[s3c2410-sdi]
you would have to append the filename of the folder or image-file to this line:
Code:
filename=
Absolute paths are preferred (and I believe that's what I made the GUI options retrieve), but relative paths kind of work too: in current versions it'll be interpreted as relative to the config file location; sufficiently old versions might interpret it as relative to the current working directory of the process instead.
If attempting to fix the problem seems like too much trouble for you, this info should let you experiment with the build you already have.