Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

HP50g -- first foray into assembly lang and sysrpl

88 views
Skip to first unread message

Robert Swan

unread,
May 18, 2008, 10:46:10 PM5/18/08
to
Having become reasonably familiar with my new hp50g, and at least
introduced myself to most of the user RPL commands, I thought I should
finally bite the bullet and have a go at some System RPL.

Oddly enough, I was was already fairly familar with Saturn assembly
language; I have owned an HP-71B since about '85 (IIRC) and enjoyed
adding a few extensions to its Forth language. I thought sysrpl
should be fairly easy in comparison. Not so sure now.

Well, enough of my background. On to the background of my questions.

I thought an interesting first challenge would be the old Mastermind
style game, "Cows and Bulls". The vanilla flavour of this game
wouldn't require great speed, but I have a variant where the computer
keeps track of possible candidates. After each of your guesses,
besides telling you so many cows and bulls, it goes through the set
of remaining candidates, eliminating those which wouldn't match this
result and tells you how many candidates remain. For example:

Guesses C B
1274 0 1
3579 1 1
6978 0 1 Possible: 3

(FYI, the remaining candidates are: 1538 3258 6534)

There is clearly quite a bit of processing early on when all 3024
candidates are still valid and a combination of sysrpl and assembly
language seemed to be called for (of course it would be cheating to
use C or ARM!).

At long last, down to my questions:

1. How should I structure shared functions in assembly language?

Having implemented the candidate list as a bitmap (just a grob), I
need one function to clear a bit when a candidate is eliminated
and another to test a bit in order to count candidates after a
guess.

The majority of the code for setting or testing a bit is identical
and I have put that code in a "PixPrep" function which returns
address and mask in registers. This code is included in the
"bmreset" function's CODE block. I have another function,
"bmtest", which calls PixPrep in the guts of "bmreset". This
works -- as long as I store the library in port 0, fails in any
other port -- but it seems dodgy. To make this clearer (maybe),
here is the skeleton:

...
NULLNAME bmtest
::
CODE
GOSUB PixPrep *** Calling inside bmreset NULLNAME block
C=C&A P
...
GOVLNG =PUSH#ALOOP
ENDCODE
;


NULLNAME bmreset
::
CODE
GOSUB PixPrep
C=-C-1 P
...
GOVLNG =GETPTRLOOP
*
* Input grob pix# on stack
* Output
* A[0] Pixel nibble's current value
* C[0] Mask of pixel
* D1 Address of pixel's nibble
* Changed
* B
*
PixPrep
GOSBVL =POP#
GOSBVL =SAVPTR
...
RTN
ENDCODE
;

...

I can see options like passing a function selector on the stack,
but I don't find that particularly appealing. I'd really like
there to be multiple known entry points within one code block.
I've probably missed this somewhere in the documentation.

2. Where is there a clear summary of the syntax differences in the
flavours (HP, MASD, others?) of sysrpl and of assembly language?

I was used to HP's Saturn instruction set and have been using
Debug4x as a development environment for this exercise, but I
would like to get away from the PC (Windows in particular)
and MASD is right there on the calculator.

Besides this, I have been confused from time to time when
tutorials downloaded from hpcalc.org were referring to a
syntax that wasn't available in the other environment. IIRC,
I couldn't find an MASD equivalent of HP's NULLNAME, but I bet
it has one. Also took me a while to work out the need for
FEXTERNAL for entry points introduced by "^".

3. Is there any documentation like the HP-71 IDS for entry points?

I had to poke around with Nosy (which is brilliant) to work out
that POP1% sets decimal mode and calls SAVPTR, both of which need
to be catered for before returning. Something warning me of
significant side-effects would be very welcome.

On the whole, I have been pleased with what I have managed to get to
grips with in the last two weeks. While I've had a 48SX since '92,
I never went beyond user RPL with it; there was paid work to do, and
that was Unix/C, so no time to get into my calculator's intricacies.
Consequently, I have missed out on all the history that has led to the
rather baroque interface that's there today. Pretty daunting to get
a handle on it now, but I don't mind a challenge.

Have fun,

Robert.
--
Robert Swan | No, not the antarctic adventurer.
swan...@gmail.com | No, not the Canberra porn monger.
| Yes, that's right, the boring one.

Raymond Del Tondo

unread,
May 19, 2008, 7:26:51 AM5/19/08
to
Hi,

here's a hint for code safety:
Don't use inter-code jumps in relocateable code.
Don't do it, never!
It leads to unsafe code, and is bad programming style.

Your call to your subroutine PixPrep is very likely to fail
if the code doesn't reside in main memory (port 0),
because it will be copied to there in pieces,
each RPL sub when it's used,
so there is a big chance that your target location 'PixPrep'
doesn't even exist in main RAM when
called from a completely different code slice.

And don't forget the always waiting garbage collection,
which will move yor code in memory.

However, if you urgently need to have various routines
call a common sub, then you should consider combining
all code slices into one single code object,
and introduce a suitable stack parameter so the code
can decide where to jump fro mthe start.


The other way to go would be s.t. like this:


RPL
NULLNAME Sub1
ASSEMBLE
CON(5) =DOCODE
REL(5) ComCodeEnd

* Actual code


RPL
NULLNAME Sub2
ASSEMBLE
CON(5) =DOCODE
REL(5) ComCodeEnd

* Code

RPL
NULLNAME Sub3
ASSEMBLE
CON(5) =DOCODE
REL(5) ComCodeEnd

* Code

PixPrep

ComCodeEnd
RPL


This will also work when the code resides in a port other than 0 .
Please note that inter-code jumps MUST ALWAYS be forward jumps.

If Sub1 Sub2 Sub3 all call PixPrep,
PixPrep has to be in the last pseudo-code object.
If PixPrep would reside in the code slice of Sub1,
Sub3 would not have a safe link to PixPrep,
because if it comes to copying to TEMPOB,
only the Sub3 would have been copied,
not Sub1 or Sub2.


HTH

Raymond

"Robert Swan" <rob...@athlonx2.gville> schrieb im Newsbeitrag
news:i867g5-...@rswan.netspace.net.au...

cyrille de brebisson

unread,
May 19, 2008, 9:25:44 AM5/19/08
to
hello,

for the syntax, I can not help you much. the only advice I can give you is
to read the AMSD documentation located in the advanced user manual for the
49/50...

NULLNAME is used for library entry that have no 'name'. MAsd is not designed
to create library (unless you make them yourself by hand). we use the CRLIB
on the calculator... and it has an equivalent for NULLNAME ($HIDDEN), read
that doc for more info on how this works.

as stated by others, unless you know what you are doing (which is not the
case yet), NEVER jump form one ASM code to another... the usual way to
handle stuff like this is to create 1 single code with an 'entry code' that
goes to a switch case type statement to do various things....

regards, cyrille


"Robert Swan" <rob...@athlonx2.gville> wrote in message
news:i867g5-...@rswan.netspace.net.au...

swan...@gmail.com

unread,
May 19, 2008, 10:31:24 PM5/19/08
to
In article <g0ro6a$ue6$01$1...@news.t-online.com>,

Raymond Del Tondo <Ih8...@nowhere.com> wrote:
>here's a hint for code safety:
>Don't use inter-code jumps in relocateable code.
>Don't do it, never!
>It leads to unsafe code, and is bad programming style.

Your advice is welcome, and makes perfect sense. I suspected as much
(I did say it seemed dodgy), but was unsure. That's why I posted.

>Your call to your subroutine PixPrep is very likely to fail
>if the code doesn't reside in main memory (port 0),
>because it will be copied to there in pieces,
>each RPL sub when it's used,
>so there is a big chance that your target location 'PixPrep'
>doesn't even exist in main RAM when
>called from a completely different code slice.

Is there some document where this process is described? There is a
lot of stuff available, but what I've seen has mostly been either
introductory or assumed great knowledge. As I said, something like
the HP-71B's IDS manuals (particularly vol I) that explains the
general workings of the system software would help me a lot.

>However, if you urgently need to have various routines
>call a common sub, then you should consider combining
>all code slices into one single code object,
>and introduce a suitable stack parameter so the code
>can decide where to jump fro mthe start.

Yeah -- what I referred to as "passing a function selector
on the stack" -- doesn't appeal too much.

>The other way to go would be s.t. like this:

But this way is exactly what I was after. Multiple entry points
to a single block of relocatable code. Worked for me straight away.

Hmmm. Again, I'm afraid we're bumping into my ignorance. So Sub1,
Sub2 and Sub3 (and PixPrep) are not all (as a result of the use of
ASSEMBLE and RPL directives) in one atomic block? Let's see if I have
this worked out right then. Structured as per your skeleton code
above, the flow for a call to Sub3 followed by Sub1 might be as
follows:

1. Sub3 invoked, and just it (including PixPrep) loaded into memory
and executed.
2. Sub1 invoked (Sub3 & PixPrep still in memory, I assume), no room
in front of Sub3, so Sub1, Sub2, Sub3 and PixPrep are all loaded
into a new block of memory and Sub1 executed.

Is this something like what happens?

Once again, I suppose, a pointer to system-level documentation
would seem to be the best cure.

>HTH

Indeed it did, Raymond. Many thanks.

Tanguy Briancon

unread,
May 21, 2008, 5:20:53 PM5/21/08
to
Robert Swan wrote:
> Having become reasonably familiar with my new hp50g, and at least
> introduced myself to most of the user RPL commands, I thought I should
> finally bite the bullet and have a go at some System RPL.
>
> Oddly enough, I was was already fairly familar with Saturn assembly
> language; I have owned an HP-71B since about '85 (IIRC) and enjoyed
> adding a few extensions to its Forth language. I thought sysrpl
> should be fairly easy in comparison. Not so sure now.

Do you know this:

http://www.hpcalc.org/details.php?id=5142


>
> Well, enough of my background. On to the background of my questions.
>
> I thought an interesting first challenge would be the old Mastermind
> style game, "Cows and Bulls". The vanilla flavour of this game
> wouldn't require great speed, but I have a variant where the computer
> keeps track of possible candidates. After each of your guesses,
> besides telling you so many cows and bulls, it goes through the set
> of remaining candidates, eliminating those which wouldn't match this
> result and tells you how many candidates remain. For example:
>
> Guesses C B
> 1274 0 1
> 3579 1 1
> 6978 0 1 Possible: 3
>
> (FYI, the remaining candidates are: 1538 3258 6534)
>
> There is clearly quite a bit of processing early on when all 3024
> candidates are still valid and a combination of sysrpl and assembly
> language seemed to be called for (of course it would be cheating to
> use C or ARM!).
>
> At long last, down to my questions:
>
> 1. How should I structure shared functions in assembly language?
>

You can't! I think that every objects (from a sys-rpl program) are
pushed on the TEMPOB (temporary objects) area. The solution is:
only one ASM program which pop on the stack a number which says
what the ASM program have to do.

> 2. Where is there a clear summary of the syntax differences in the
> flavours (HP, MASD, others?) of sysrpl and of assembly language?

No I don't think so.

> I was used to HP's Saturn instruction set and have been using
> Debug4x as a development environment for this exercise, but I
> would like to get away from the PC (Windows in particular)
> and MASD is right there on the calculator.
>
> Besides this, I have been confused from time to time when
> tutorials downloaded from hpcalc.org were referring to a
> syntax that wasn't available in the other environment. IIRC,
> I couldn't find an MASD equivalent of HP's NULLNAME, but I bet
> it has one. Also took me a while to work out the need for
> FEXTERNAL for entry points introduced by "^".

Do you know this:

http://staff.science.uva.nl/~dominik/hpcalc/


If you read french http://www.courbis.fr/spip.php?rubrique8
regardez voyage au centre de la hp 48g.

If you can't read french:

http://www.courbis.fr/spip.php?rubrique9

you will find a translation for hp48s(x).
Of course hp48s,49g,50g are not the same but
mostly they are still very intersting books on hp48
models.


Raymond Del Tondo

unread,
May 22, 2008, 4:34:47 PM5/22/08
to
Hi Robert,

here's a short description of what happens,
given my code construct with Sub1 Sub2 Sub3, and PixPrep.
Also assume the whole code resides in a location
other than main RAM (port 0) .


If you call Sub3, the code slice between the Sub3 entry
and ComCodeEnd will be copied to TEMPOB
as one monolithic block.

If you call Sub2, the code slice between the Sub2 entry
and ComCodeEnd will be copied to TEMPOB
as one monolithic block.
This includes the Sub3 entry in this case.

If you call Sub1, the code slice between the Sub1 entry
and ComCodeEnd will be copied to TEMPOB
as one monolithic block.
This includes the Sub2 and Sub3 entries in this case.

This works because the appriorate length fields
span from the distinct start to the common end,
or in other words, Sub1 includes Sub2,
which includes Sub3, which includes PixPrep.


> 1. Sub3 invoked, and just it (including PixPrep) loaded into memory
> and executed.
> 2. Sub1 invoked (Sub3 & PixPrep still in memory, I assume),
>

At this point you can simply forget about any previous invocation
of Sub3, as the new TEMPOB copy has no relation to the old one.

Even if the old TEMPOB code is still in memory, consider it gone.

There are many documents about RPL and ML programming,
most of them can be found on www.hpcalc.org .

There are RPL and ML tutorials, RPL and ML entry lists and descriptions,
also some fundamental docs like RPLMAN.doc , and much more;-)


Have fun

Raymond


0 new messages