HP Forums
(HP48) Assembler Question - Printable Version

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Software Libraries (/forum-10.html)
+--- Forum: General Software Library (/forum-13.html)
+--- Thread: (HP48) Assembler Question (/thread-19560.html)



(HP48) Assembler Question - Hiwi - 02-14-2023 08:52 AM

Hi,
i am trying to pop a real from the stack to use this value for further calculations.
I expected the result in A(W). But the following Code, causes a reset or memory clear :-) :

...
GOSBVL =POP1%
GOSBVL =SAVEPTR
% do something with A(W)
SETHEX % POP1 sets DEC Mode
GOSBVL =GETPTRLOOP

How do I use POP1% in the right way? Do i have to increase D+1 and D1+5 (did not worked at all) ?

My 2nd question is regarding the =LOOP entrypoint on my G with ROM Version M with MetaKernel 2.3

GOVLNG =LOOP causes a soft reset

This simple code does not work
GOSBVL =SAVEPTR % save regs
% some instructions
GOSBVL =GETPTR % restore regs
GOVLNG =LOOP % exit to RPL

I am using this one instead, which never made any problems:

GOSBVL =SAVEPTR
% some instructions
GOSBVL =GETPTRLOOP % exit to RPL

But examining the romcode, this should be the same.

Ralf


RE: (HP48) Assembler Question - Giuseppe Donnini - 02-14-2023 01:19 PM

1. HOW TO CALL POP1%

POP1% already contains a jump to SAVPTR. Here is what its disassembly looks like (I’ve added some comments to make it as readable as possible):

Code:
29FDA          =POP1%
29FDA 147               C=DAT1  A         * Read address of real number object on stack level 1.
29FDD 137               CD1EX             * D1:Point to real number object; C[A]:Save RPL variable D (Data Stack Pointer).
29FE0 174               D1=D1+  5         * Skip prologue address of real number object (DOREAL).
29FE3 1537              A=DAT1  W         * Read value of real number object.
29FE7 135               D1=C              * Restore RPL variable D (Data Stack Pointer).
29FEA 174               D1=D1+  5         * (D1 holds RPL variable D) Point to address of next object. \ Effectively drops real
29FED E7                D=D+1   A         * (D[A] holds RPL variable M) Increment free memory counter. /   number from stack.
29FEF 05                SETDEC            * Set decimal arithmetic mode.
29FF1 8DB9760           GOVLNG  =SAVPTR   * Get RPL variables out of the way by saving them in reserved system RAM.

So, here’s the right way to do it:

Code:
        GOSBVL  =POP1%
* ...
        SETHEX
        GOVLNG  =GETPTRLOOP

Also note that GETPTRLOOP passes control back to System RPL, so you should use GOVLNG instead of GOSBVL. It’s not a good idea to leave garbage on the hardware return stack.

 
2. LOOP vs. Loop

In the world of RPL and SATURN Assembly, everything is case sensitive.

LOOP can be one of two things:

  1. Either it is an RPL primitive code object used together with DO (or a similar object) in order to build a definite loop control structure in System RPL.
    This is obviously not what you want, since your program is written in SATURN assembly.

     
  2. Or it is a (macro-like) compiler directive instructing the compiler to replace the LOOP statement by the following actual code, representing the RPL inner loop:

    Code:
            A=DAT0  A
            D0=D0+  5
            PC=(A)

    Whether LOOP, in the sense at hand, is recognized or not, depends on the compiler you are using. RPLCOMP.EXE does recognize it, SASM.EXE (which is not a compiler) doesn't. (Note that LOOP is recognized by RPLCOMP.EXE if it is either the first word on the line, or the second word preceded by a label.)


Loop, on the other hand, is the machine-language entry point you are looking for.

Code:
2D564          =Loop
2D564 142               A=DAT0  A
2D567 164               D0=D0+  5
2D56A 808C              PC=(A)

 

To sum it all up: If you want to give control back to the RPL world:
  • Use the following in-line code:

    Code:
            A=DAT0  A
            D0=D0+  5
            PC=(A)

     
  • Or, to save some typing, use the LOOP statement, if you are using RPLCOMP.EXE (or a compiler that recognizes the LOOP statement). This will obviously result in the exact same compiled code.

     
  • Or jump to Loop at the end of your assembly program.

    Code:
    8D465D2           GOVLNG  =Loop

    This method is slower than in-line code, because it takes some CPU cycles to carry out the jump to address #2D564h, but it will save three nibbles of space (7 vs. 10).

     
  • If, before going back to RPL, you also need to restore the RPL variables, you can jump to a (machine-language) entry point that combines both actions, e.g. GETPTRLOOP, which dissassembles to:

    Code:
    05143          =GETPTRLOOP
    05143 8E9861            GOSUBL  =GETPTR
    05149 142               A=DAT0  A
    0514C 164               D0=D0+  5
    0514F 808C              PC=(A)



RE: (HP48) Assembler Question - Hiwi - 02-15-2023 11:08 AM

Hi Giuseppe,
thank you for the extensive reply. Perfect!

POP1% now works, i did not realize, that SAVEPTR is already included.

I will try the LOOP suggestions, i am already using alternatives, so i was wondering if the problem was only metakernel related.

Thanks again.
Ralf


RE: (HP48) Assembler Question - Giuseppe Donnini - 02-18-2023 12:43 PM

You’re welcome. Note that, conversely, PUSH% already includes a SETHEX instruction as well as a call to GETPTR. Therefore, if in the middle section of your code, you intend to recall the RPL variables in order to modify them yourself, you have to call SAVPTR again before calling PUSH%. Otherwise, the relevant CPU registers will be overwritten by the former (and now obsolete) values.


RE: (HP48) Assembler Question - Hiwi - 03-02-2023 10:53 AM

Hi Giuseppe,
yes i made another program which used push% many times, but in this case i made it intuitively
correct.

Is there a good tool which can dissasemble this entry points? Like a memory browser. I have only the jazz disasm, which can disam only code or sysrpl.

Ralf