Date : Fri, 16 Dec 2011 17:43:26 +0100
From : kortink@... (John Kortink)
Subject: 32016 + 32082
On Fri, 16 Dec 2011 15:23:46 +0000 (WET), Peter Coghlan
<BBCMICRO@...> wrote:
>>>
>>>BBC BASIC uses the 6502 stack like any 6502 program but to avoid overflowing
>>>it when processing (for example) recursive procedure or function calls, BASIC
>>>saves the contents of the 6502 stack on its own larger stack and reinitialises
>>>the 6502 stack pointer each time it processes a procedure or function,
>>>restoring it on return.
>>
>>The interesting thing, though, is that it doesn't do this to
>>avoid ordinary stack overflow due to deeply nested PROC/FN
>>calls, but primarily for performance reasons. Theoretically,
>>the BASIC stack would be a perfect replacement for the 6502
>>stack, if it was used exclusively and consistently.
>>
>>But in the PROC/FN call overhead, where formal and actual
>>parameters are bound and implicit LOCALs (i.e. formal
>>parameters with pre-existing names) are saved, processing
>>would be pretty slow if all the pushes and pops were done
>>via the BASIC stack. And only because, even in that process,
>>nesting can occur (since an actual parameter expression can
>>contain FNs, which can contain yet other FNs, etc.), it needs
>>to account for that, by pushing and popping the entire 6502
>>stack (which is far quicker in the end).
>>
>
>It's been a while since I delved deeply into the BASIC ROM but Mark Plumbley
>in his "BASIC ROM User Guide for the BBC Microcomputer and Acorn Electron",
>seems to say fairly categorically that parameters and local variables
>are pushed directly onto the BASIC stack after the contents of the 6502
>stack has already been pushed onto the BASIC stack (however, PTRA, PTRB,
>a count of the parameters and a token to indicate whether a PROC or FN
>is being processed are subsequently pushed onto the 6502 stack).
>As well as explicitly stating that "The 6502 stack is not very big - only 256
>bytes - and saving it in this manner allows deep recursion of FNs and PROCs
>without overflowing the small 6502 stack", he also states that processing a
>PROC or FN results in a JSR to the statement interpreter while ENDPROC and
>function return result in the execution of a corresponding RTS. This gives a
>strong hint as to the basis for his statement.
Your point eludes me. That simply describes what is happening
in the current implementation (if somewhat incomplete). But
does not argue that it could not have been done otherwise.
Obviously (but perhaps that's just from my point of view) even
a JSR can be performed via the BASIC stack (push address, JMP,
pull address), i.e., theoretically, BASIC could run without
/ever/ using the 6502 stack. So, even though it's a purely
theoretical point, any use of the 6502 stack is basically
optimization (or just plain convenient in most cases).
Also (and this is from my foray into BASIC 4r32 to give it 24-bit
variable addressing, which, among many other things, hits exactly
the code we're talking about) what actually happens is that first
the addresses of the formal parameters are pushed onto the 6502
stack, then the actual parameters are evaluated and their values
are pushed onto the BASIC stack, then the assignments (actual to
formal) take place. (I'm ignoring LOCAL processing here, but that
is done via the BASIC stack only). Again, that does not mean that
the formal parameter addresses could not have been pushed onto the
BASIC stack instead. But it would complicate the processing quite
a bit, and cause a considerable performance hit.
So, the /main/ reason for saving the 6502 stack on every PROC/FN
(besides a couple of other things) is basically the fact that the
formal parameter addresses are on it while the actual parameters
are being evaluated (which can cause further calls to PROC/FNs).
And, in contrast to the other stuff, the size of that is, to some
extent, unbound. You could probably crash BASIC in a single call
if you gave the relevant PROC or FN enough parameters.
John Kortink
--
Email : kortink@...
Homepage : http://www.inter.nl.net/users/J.Kortink