Correct Maths Stack usage (CHRIX/RESRI)

Anything QL Software or Programming Related.
User avatar
janbredenbeek
Trump Card
Posts: 221
Joined: Wed Jan 21, 2015 4:54 pm
Location: Hilversum, The Netherlands

Re: Correct Maths Stack usage (CHRIX/RESRI)

Postby janbredenbeek » Tue Feb 13, 2018 10:33 am

pjw wrote:Yet the SMSQ/E Bible says:

Code: Select all

Vector $11A Reserve Room on Arithmetic Stack QA.RESRI
Call parameters                         Return parameters
D1.L Number of bytes required          D1 ???
D2                                     D2.L ???
D3                                     D3.L ???
A0                                     A0 Preserved
A1 Pointer to RI stack (rel. A6)       A1 ???
A2                                     A2 Preserved
A3                                     A3 Preserved
Error returns:
IMEM out of memory [SMSQ]
none [QDOS]

It may have been early days when Pennell wrote his book - or just a typo

Interesting! I have to delve deeper into the various disassemblies and Minerva/SMSQ source codes, but from the peeks I've done in the past into the various BV.CHxx routines I gathered that A1 has always been preserved (even the SMSQ/E code contains MOVEM.L Ax,-(A7) at the start and MOVEM.L (A7)+,Ax at the end). I couldn't find any instruction that stores A1 somewhere either (remember this call has various entry points for the different S*BASIC areas, which use D2.L as key to the pointer to the area to be moved).
I even remember a comment from Lau that it would be nice if BV.CHRIX would return A1 pointing to BV.RIP(A6) which would save programmers a MOVE instruction afterwards. However, if the original behaviour is to preserve A1, this would be prone to break software which relies on it...

regards, Jan.


User avatar
pjw
Gold Card
Posts: 294
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway

Re: Correct Maths Stack usage (CHRIX/RESRI)

Postby pjw » Tue Feb 13, 2018 11:50 am

Mr Dunbar wrote:PS. If you need to allocate space on the stack for a result, and you already fetched some parameters, make sure that you allocate the space required minus the space used by the parameters. <>
Sometimes it is simpler to zero out what you have on the stack and start again, eg: You got one long (6 bytes), and want to return a word at the end, but you have other stuff going on that may require the use of the stack. The stack is never going to be shrunk while youre at it, although under QDOS it may move as a result of external events:

Code: Select all

   get one long
   move.l (a6,a1.l),d1
   addq.l #6,$58(a6)
..
   la di da
..
   bv.chrix and all that
   subq.l #2,$58(a6)
   move.l $58(a6),a1
   move.w dx,(a6,a1.l)

If you fetch multiple strings, however, things get rather fiddly, what with length counts and odd lengths. You can save yourself some trouble with the following shortcut:

Code: Select all

On entry to your funtion:
       move.l bv_rip(a6),d7        ;save "empty" stack pointer
       sub.l  bv_ribas(a6),d7      ;make it relative to BAS
       bsr.s  fetch_strings        ;fetch some strings (this may move the BASIC area)
..
       la di da
..
       add.l  bv_ribas(a6),d7      ;restore old relationship
       subq.l #2,d7               ;leave room for integer return
       move.l d7,bv_rip(a6)        ;reset stack to status quo ante - 2
       move.l d7,a1
       move.w dx,(a6,a1.l)


Per
Assumptions should only be a first resort when the cost of being wrong is less than the trouble of finding out the facts! - pjw, 2016
User avatar
pjw
Gold Card
Posts: 294
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway

Re: Correct Maths Stack usage (CHRIX/RESRI)

Postby pjw » Tue Feb 13, 2018 11:52 am

pjw wrote:
Mr Dunbar wrote:PS. If you need to allocate space on the stack for a result, and you already fetched some parameters, make sure that you allocate the space required minus the space used by the parameters. <>
Sometimes it is simpler to zero out what you have on the stack and start again, eg: You got one long (6 bytes), and want to return a word at the end, but you have other stuff going on that may require the use of the stack. The stack is never going to be shrunk while youre at it, although under QDOS it may move as a result of external events:

Code: Select all

   get one long
   move.l (a6,a1.l),d1
   addq.l #6,$58(a6)
..
   la di da
..
   subq.l #2,$58(a6)      ; the ristack doesnt shrink mid-session
   move.l $58(a6),a1
   move.w dx,(a6,a1.l)

If you fetch multiple strings, however, things get rather fiddly, what with length counts and odd lengths. You can save yourself some trouble with the following shortcut:

Code: Select all

On entry to your funtion:
       move.l bv_rip(a6),d7        ;save "empty" stack pointer
       sub.l  bv_ribas(a6),d7      ;make it relative to BAS
       bsr.s  fetch_strings        ;fetch some strings (this may move the BASIC area)
..
       la di da
..
       add.l  bv_ribas(a6),d7      ;restore old relationship
       subq.l #2,d7               ;leave room for integer return
       move.l d7,bv_rip(a6)        ;reset stack to status quo ante - 2
       move.l d7,a1
       move.w dx,(a6,a1.l)


Per
Assumptions should only be a first resort when the cost of being wrong is less than the trouble of finding out the facts! - pjw, 2016
User avatar
mk79
Bent Pin Expansion Port
Posts: 98
Joined: Sun Feb 02, 2014 10:54 am

Re: Correct Maths Stack usage (CHRIX/RESRI)

Postby mk79 » Tue Feb 13, 2018 12:24 pm

NormanDunbar wrote:Looks good to me Martyn.

If you have qmon/qmon2, put a breakpoint on it and see what's in A1 before you load it from BV_RIP. It won't be the stack! ;)

Qmon used to allow a trap #15 in your code to jump into the qmon monitor. That got removed from qmon2 for some reason. A big omission in my opinion.

You can have a permanent breakpoint using either dc.l $4afbedeb ("Enter DEBugger") or continue to use "trap #15", the latter however must be enabled by the command "tl 15" (IIRC "Trap Level 15") to enter QMON, otherwise it will be ignored.

Marcel


User avatar
NormanDunbar
Gold Card
Posts: 364
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: Correct Maths Stack usage (CHRIX/RESRI)

Postby NormanDunbar » Tue Feb 13, 2018 9:40 pm

Thanks Marcel, that worked perfectly. Trap #15 once again brings QMON to the fore.

I added a TRAP #15 to DJToolkit's DJTK_VER$ function. This takes no parameters and returns a 4 character string, requiring 6 bytes on the stack.

PRINT DJTK_VER$

QMON was activated. A1 was set to zero.

PRINT 'xxxx' & DJTK_VER$

QMON was activated. A1 was set to FFFFFFFA or -6 which is the space used on the stack by the 4 character string plus its word count.


Thus, my assertion that on entry to a function, A1 is NOT a suitable value for the maths stack stands. :P :P :P Yah boo sucks! (Am I a plonker or what?)

Seriously, this is exactly what caused me lots of debugging way back when. Every book I had/have says that A1 will be a suitable value for the maths stack on entry to a function. None of my functions that took no parameters bothered to do anything with A1, so they simply blew up. It was only when QMON was bought/purchased and used that I finally discovered the anomalies - it's only set if you fetch some parameters and not if you don't.

HTH

Cheers,
Norm.


Why do they put lightning conductors on churches?
How come Tarzan never grew a beard?
User avatar
tofro
QL Wafer Drive
Posts: 1292
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: Correct Maths Stack usage (CHRIX/RESRI)

Postby tofro » Tue Feb 13, 2018 10:17 pm

The only thing the "Technical Guide" claims is

The top of the arithmetic stack is usually pointed to by A1.


(So, that's apparently a book you don't have, Norm, but should) ;)

This is probably meant to say "you should make a1 point to it" and Pennel took it as "the system makes it point there".

My experience is the same: Without pulling parameters from BASIC or loading it from BV.CHRIX, a1 may point to anywhere but the math stack upon entering a BASIC FN or PROC.

Tobias


User avatar
NormanDunbar
Gold Card
Posts: 364
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: Correct Maths Stack usage (CHRIX/RESRI)

Postby NormanDunbar » Tue Feb 13, 2018 11:14 pm

Hi Tofro.

I do have it, bit its a huge A4loose leaf binder rather than a book. I ptrefer books.


Cheers,
Norm.


Why do they put lightning conductors on churches?
How come Tarzan never grew a beard?
User avatar
janbredenbeek
Trump Card
Posts: 221
Joined: Wed Jan 21, 2015 4:54 pm
Location: Hilversum, The Netherlands

Re: Correct Maths Stack usage (CHRIX/RESRI)

Postby janbredenbeek » Tue Feb 13, 2018 11:38 pm

This is what the QL Technical Manual says about BV.CHRIX:
BV.CHRIX is used to reserve space on the arithmetic stack (A6,A 1). On entry, the number of bytes required should be in D1.L: DO to D3 are smashed.
Since not only the stack but the whole SuperBASIC area may move during the call, the arithmetic stack pointer should be saved in BV_RIP(A6), whence it should be retrieved after the call has been completed.

However this doesn't say that on entry to a procedure or function A1 indeed points to the top of the RI stack. It only says that If you want to make sure there's enough room while you are doing something on the RI stack, you should save the current stack pointer to BV.RIP(A6), then call BV.CHRIX, and then retrieve A1 again from BV.RIP(A6). This is also what Pennell says.
In any case, BV.RIP(A6) should always point to the top of the RI stack but you should make no assumptions about A1 on entry, so always do a MOVE.L BV.RIP(A6),A1 before doing anything (if your procedure has parameters, you should first call the CA.GTxxx vectors anyway to evaluate them, which will also return (A6,A1.L) pointing to the top of the RI stack).

regards, Jan.


User avatar
janbredenbeek
Trump Card
Posts: 221
Joined: Wed Jan 21, 2015 4:54 pm
Location: Hilversum, The Netherlands

Re: Correct Maths Stack usage (CHRIX/RESRI)

Postby janbredenbeek » Tue Feb 13, 2018 11:47 pm

Hi Norman,
NormanDunbar wrote:Thanks Marcel, that worked perfectly. Trap #15 once again brings QMON to the fore.

I added a TRAP #15 to DJToolkit's DJTK_VER$ function. This takes no parameters and returns a 4 character string, requiring 6 bytes on the stack.

PRINT DJTK_VER$

QMON was activated. A1 was set to zero.

PRINT 'xxxx' & DJTK_VER$

QMON was activated. A1 was set to FFFFFFFA or -6 which is the space used on the stack by the 4 character string plus its word count.

Thus, my assertion that on entry to a function, A1 is NOT a suitable value for the maths stack stands. :P :P :P Yah boo sucks! (Am I a plonker or what?)

Most procedures and functions have parameters, which must be evaluated first by calling the CA.GTxxx vectors. These return (A6,A1.L) pointing to the top of the RI stack.
However your function doesn't have a parameter so it doesn't have to call the CA.GTxxx vectors. In that case, you have to load A1 from BV.RIP(A6) first before putting the result on the stack (after calling BV.CHRIX first of course).

regards, Jan.


martyn_hill
Gold Card
Posts: 339
Joined: Sat Oct 25, 2014 9:53 am

Re: Correct Maths Stack usage (CHRIX/RESRI)

Postby martyn_hill » Tue Feb 13, 2018 11:52 pm

Hi everyone

Very interesting discussion - thank you!

If I may return to one of the original questions very briefly - "Must we pre-load a1 with bv_rip(a6) BEFORE calling CHRIX/RESRI?", can we agree that this step is unnecessary (contrary to the SMSQ reference guide and source code comments)?

Following Jan's comments, I've since perused the Minerva source and found chstk.asm which - as Jan mentioned - places no such requirement on a1 holding anything of interest before the relevant check/allocate (CHRIX just being the more common example.)

Still can't seem to find the equivalent module in the SMSQ source code, mind-you.



Return to “Software & Programming”

Who is online

Users browsing this forum: No registered users and 2 guests