Hi everyone
I am perplexed regarding a small point around correct use of the Maths stack. I am well acquainted with Mr. Dunbar's authoritative exposition on the subject (found on Dilwyn's site)  my favorite goto reference on this knarly topic...
Then I read both the SMSQ Reference Guide, as well as numerous mentions littered throughout the SMSQ source code.
My question is this: Before calling the CHRIX/RESRI vector to check that/reserve sufficient space is available, is it necessary to preload A1 with the current value of BVRIP(a6)?
We know that we need to reload A1 with BVRIP(a6) _after_ calling CHRIX/RESRI and before adjusting (sub) A1 with the required space ready for returning a value to SBasic (equal to what was asked for in the CHRIX/RESRI call.) and then saving the adjusted A1 back to BVRIP(a6).
That's all OK, but do we _really_ need to load A1 _before_ the vector call as well?
Mr. Dunbar doesn't mention such a requirement, yet QA.RESRI specifically states that A1 should point to the current Maths stack as a parameter on _entry_.
I did attempt to search the SMSQ source code to find the actual QA.RESI routine, but failed dismally.
Thoughts, my friends?
Correct Maths Stack usage (CHRIX/RESRI)

 Gold Card
 Posts: 339
 Joined: Sat Oct 25, 2014 9:53 am
 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)
Mr Dunbar? That's me! And perhaps a little formal. Call me scumbag instead!
Off the top of my head, when you enter into a function or procedure, written in assembly, the value in A1 has nothing at all to do with the maths stack!
If you call the parameter fetching routines, then it will be set correctly. If you have no parameters to fetch, and you need to return something, load A1 from BV_RIP(A6) or your function will die a horrible death on exit.
Here are some quotes from "the Book" (http://qdosmsq.dunbarit.co.uk/download ... sembly.pdf) Pages 120 and onwards:
One of the first things I learned when writing extensions to SuperBasic was that on entry to a
function or procedure, the A1 register is set to a value corresponding to the top of the maths stack.
This is a myth and is not correct.
The value in register A1 can be anything on entry to a machine code function or procedure. I have
done a lot of investigating (thanks to QMON2) and come up with the following rule:
If you want a suitable value in A1 for the top of the maths stack, then either fetch some parameters,
or, load it from BV_RIP.
This means that if a function wants to return a value  which functions usually do  and the function
has no parameters then you must load A1 from BV_RIP(A6) before calling the BV_CHRIX vector to
reserve space. As I found out to my cost, not setting A1 is a good way to trash the system!
If your function does have parameters, then AFTER they have been fetched, A1 is set ok, up until
that time, it is not and has the following possible values:
If A1 is a negative number, then your function has been called as part of an expression such as:
The number in A1.L is the number of bytes that have already been used on the maths stack for the
‘10’ in this case. This will be 6 as the 10 will be stored as a floating point number.
If the number in A1 is zero, then your function has been called thus:
or
and no bytes have been used on the maths stack yet.
If A1.L is greater than zero then this implies that there are A1.L many bytes available on the
maths stack and calling BV_CHRIX to allocate stack space will not move the maths stack around in
memory.
So that is the real situation and not as specified in the documentation. I took ages to debug one
simple function I wrote, which had no parameters and required some space on the maths stack for
its result.
HTH
Cheers,
Norm. (Aka Mr Dunbar!!!)
Off the top of my head, when you enter into a function or procedure, written in assembly, the value in A1 has nothing at all to do with the maths stack!
If you call the parameter fetching routines, then it will be set correctly. If you have no parameters to fetch, and you need to return something, load A1 from BV_RIP(A6) or your function will die a horrible death on exit.
Here are some quotes from "the Book" (http://qdosmsq.dunbarit.co.uk/download ... sembly.pdf) Pages 120 and onwards:
One of the first things I learned when writing extensions to SuperBasic was that on entry to a
function or procedure, the A1 register is set to a value corresponding to the top of the maths stack.
This is a myth and is not correct.
The value in register A1 can be anything on entry to a machine code function or procedure. I have
done a lot of investigating (thanks to QMON2) and come up with the following rule:
If you want a suitable value in A1 for the top of the maths stack, then either fetch some parameters,
or, load it from BV_RIP.
This means that if a function wants to return a value  which functions usually do  and the function
has no parameters then you must load A1 from BV_RIP(A6) before calling the BV_CHRIX vector to
reserve space. As I found out to my cost, not setting A1 is a good way to trash the system!
If your function does have parameters, then AFTER they have been fetched, A1 is set ok, up until
that time, it is not and has the following possible values:
If A1 is a negative number, then your function has been called as part of an expression such as:
Code: Select all
PRINT 10 ∗ MY_FUNCTION( p1 , p2 , p3 . . . . )
The number in A1.L is the number of bytes that have already been used on the maths stack for the
‘10’ in this case. This will be 6 as the 10 will be stored as a floating point number.
If the number in A1 is zero, then your function has been called thus:
Code: Select all
PRINT MY_FUNCTION( p1 , p2 , p3 . . . . )
or
Code: Select all
PRINT MY_FUNCTION( p1 , p2 , p3 . . . . ) + 10
and no bytes have been used on the maths stack yet.
If A1.L is greater than zero then this implies that there are A1.L many bytes available on the
maths stack and calling BV_CHRIX to allocate stack space will not move the maths stack around in
memory.
So that is the real situation and not as specified in the documentation. I took ages to debug one
simple function I wrote, which had no parameters and required some space on the maths stack for
its result.
HTH
Cheers,
Norm. (Aka Mr Dunbar!!!)
Why do they put lightning conductors on churches?
How come Tarzan never grew a beard?
How come Tarzan never grew a beard?
 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)
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.
I used to think it was ok to fetch, say, three FPs at 18 bytes, then ask for 24 to return 24 bytes (say a string) but I got crashed out so many times I went hunting and  although it was a long time ago  I found out that if you needed 24 bytes then don't make the stack any bigger, subtract the 18 for the 3 FPs from the 24 and allocate the spare 6 bytes.
Up until I wrote DJToolkit, which is where I encountered most of my maths stack problem areas, I was of the opinion, from books and articles in the then ever present magazines, that the stack could be treated with somewhat reckless abandon, as long as you didn't take things too far.
It was not the case. If you look in the DJToolkit source code, you will see that in "float_d1" and "integer_d1" I set d2 to be the number of bytes that I need for the result, minus the number I used on fetching parameters. I also load A1 from BV_RIP anyway!
Cheers,
Norm.
I used to think it was ok to fetch, say, three FPs at 18 bytes, then ask for 24 to return 24 bytes (say a string) but I got crashed out so many times I went hunting and  although it was a long time ago  I found out that if you needed 24 bytes then don't make the stack any bigger, subtract the 18 for the 3 FPs from the 24 and allocate the spare 6 bytes.
Up until I wrote DJToolkit, which is where I encountered most of my maths stack problem areas, I was of the opinion, from books and articles in the then ever present magazines, that the stack could be treated with somewhat reckless abandon, as long as you didn't take things too far.
It was not the case. If you look in the DJToolkit source code, you will see that in "float_d1" and "integer_d1" I set d2 to be the number of bytes that I need for the result, minus the number I used on fetching parameters. I also load A1 from BV_RIP anyway!
Cheers,
Norm.
Why do they put lightning conductors on churches?
How come Tarzan never grew a beard?
How come Tarzan never grew a beard?

 Gold Card
 Posts: 339
 Joined: Sat Oct 25, 2014 9:53 am
Re: Correct Maths Stack usage (CHRIX/RESRI)
Terrific, Norm thank you for clearing that up for me!
So, to test my understanding, here's a very simple NET% function what I wrote (simultaneously it seems with Mr Head's latest implementation in IPNet/Router), that I believe obeys all the rules for the simpler usecase of an SBasic FN with no params, returning an INT (please correct me if wrong!):
So, to test my understanding, here's a very simple NET% function what I wrote (simultaneously it seems with Mr Head's latest implementation in IPNet/Router), that I believe obeys all the rules for the simpler usecase of an SBasic FN with no params, returning an INT (please correct me if wrong!):
Code: Select all
* NET% FuNction definition
* Simply returns the currently set NET Station Number (SELF) sv_netnr from $37(SYSVARS)
*
netf
moveq #mt.inf,d0 ;find the sysvars
trap #1
moveq #0,d5
move.b sv_netnr(a0),d5 ; fetch NET Station Number from $37(SYSVARS)
move.l bv_rip(a6),a1 ; fetch current stack ptr in to a1  ready for CHRIX/RESRI  is this really needed? *** ND says YES!
moveq #2,d1 ; reserve 2xbytes for INT result
move.w bv_chrix,a2 ; check and make room if needed
jsr (a2)
move.l bv_rip(a6),a1 ; fetch (possibly updated) stack ptr in to a1
suba.l #2,a1 ; adjust for an INT result
move.l a1,bv_rip(a6) ; update BV_RIP with new stack ptr
move.w d5,0(a6,a1.l) ; store sv_netnr on the Maths stack
moveq #3,d4 ; flag an INT result
moveq #0,d0 ; flag no error
rts
 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)
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.
Cheers,
Norm.
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.
Cheers,
Norm.
Why do they put lightning conductors on churches?
How come Tarzan never grew a beard?
How come Tarzan never grew a beard?
 janbredenbeek
 Trump Card
 Posts: 221
 Joined: Wed Jan 21, 2015 4:54 pm
 Location: Hilversum, The Netherlands
Re: Correct Maths Stack usage (CHRIX/RESRI)
Martyn, Norman,
There is no need to preload A1 with the value of BV.RIP. The 'Pennell bible' lists BV.CHRIX as having only one parameter (D1: amount of space needed) and A1 as 'preserved'.
Of course, you need to load A1 with BV.RIP(A6) afterwards since areas may have been moved.
Jan.
There is no need to preload A1 with the value of BV.RIP. The 'Pennell bible' lists BV.CHRIX as having only one parameter (D1: amount of space needed) and A1 as 'preserved'.
Of course, you need to load A1 with BV.RIP(A6) afterwards since areas may have been moved.
Jan.
 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)
Hi Jan,
I'm afraid I disagree. If a function takes no parameters, A1 is not a suitable maths stack pointer until loaded from BV_RIP. I speak from bitter experience.
None of the books mention it.
Unless SMSQ/E is differnt behaviour to QDOS. I feel an experiment coming on.....
Cheers,
Norm.
I'm afraid I disagree. If a function takes no parameters, A1 is not a suitable maths stack pointer until loaded from BV_RIP. I speak from bitter experience.
None of the books mention it.
Unless SMSQ/E is differnt behaviour to QDOS. I feel an experiment coming on.....
Cheers,
Norm.
Why do they put lightning conductors on churches?
How come Tarzan never grew a beard?
How come Tarzan never grew a beard?
Re: Correct Maths Stack usage (CHRIX/RESRI)
janbredenbeek wrote:Martyn, Norman,
There is no need to preload A1 with the value of BV.RIP. The 'Pennell bible' lists BV.CHRIX as having only one parameter (D1: amount of space needed) and A1 as 'preserved'.
Of course, you need to load A1 with BV.RIP(A6) afterwards since areas may have been moved.
Jan.
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
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
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
Re: Correct Maths Stack usage (CHRIX/RESRI)
Martyn, may I suggest a wee tweak?
It saves about six bytes and looks less "clunky". Just my two cents..
Code: Select all
move.w bv_chrix,a2 ; check and make room if needed
jsr (a2)
sub.l #2,bv_rip(a6) ; adjust for an INT result
move.l a1,bv_rip(a6) ; update BV_RIP with new stack ptr
It saves about six bytes and looks less "clunky". Just my two cents..
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
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
Re: Correct Maths Stack usage (CHRIX/RESRI)
PS: IIRC, on out of memory QDOS returns directly to SuperBASIC (with or without an ERR_OM?) while SMSQ/E returns an error code in D0. So perhaps your code should cater for this (admittedly unlikely) event?
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
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
Return to “Software & Programming”
Who is online
Users browsing this forum: Yahoo [Bot] and 4 guests