Submitted by Steve Fewell
Details of procedure or function calls are stored on the BASIC stack (the latest function or procedure call is stored
on the 6502 stack). For this reason, there is no limit for the number of nested Procedure or function calls - that is
except for Memory limitations. In a simple skeleton program I was able to nest either 2162 procedure calls or 936 function
Firstly, this routine Loads A with #&A4 (The Keyword-token value for FN).
[&B019] Store the Keyword token (in A) in location &27. This value will specify whether we are calling a
function (FN - code #&A4) or a procedure (PROC - code #&A2).
Load A with the 6502 Stack pointer value.
Add the BASIC Stack pointer LSB (from location &04) to the value in A (i.e. as the Stack Pointer is usually a negative
value (i.e. #&FF (-1), #&FD (-3), etc...), this will subtract the 6502 stack pointer value from the BASIC stack LSB
Next, call routine &BD1E to store the new (decremented) Stack Pointer value in locations (&04-&05). The BASIC
Stack pointer MSB (&05) is decremented by 1. If the new BASIC Stack pointer value is less than the BASIC Heap
then issue 'No Room' error; Otherwise, if there is the required amount of space, then return.
Store the 6502 Stack pointer on the BASIC stack (at the location pointed to by (&04-&05)).
Store the contents of the 6502 Stack (&0100-&1FF) starting from the location offset by (X + 1) to the start of the
6502 stack (location &01FF) on the BASIC Stack (starting at location (&04-&05) + 1. This area of the stack
is the amount of the stack that is in current usage. The 6502 stack is copied to the BASIC Stack in order that it can be
restored back to its current state again after the Procedure has exited - as it may contains details of a previous nested
Procedure or function call. I.e. if the current stack pointer is #&FC then locations &01FC-&01FF would be
[&B033] Set the 6502 Stack pointer to #&FF (i.e. meaning that it doesn't contain any values yet).
Push the value from location &27 (The BASIC token value - indicating whether this is a FuNction or a PROCedure
call) to the 6502 Stack (i.e. location &01FF).
Push the 3-byte current program location (the location after the FN/PROC keyword, from BASIC text pointer A locations
&0A-&0B and &0C (offset)) to the 6502 stack (at locations &01FC to &01FE).
Set A and X to the BASIC text pointer B offset (&1B).
Add the BASIC Text pointer B LSB address to A (to update it with the offset value). Set Y to the BASIC text pointer
B MSB address - and increment Y if the addition of the offset and the LSB address overflowed (and clear the carry flag).
Now A and Y contain the BASIC text pointer B address (updated with the offset value).
Subtract #&02 from A (the LSB of the BASIC text pointer B address + offset) and store the result in location &37.
If the carry flag is set then subtract 1 from Y (the MSB of the BASIC text pointer B address + offset).
Store the value in Y to location &38, so that (&37-&38) point to the PROC/FN keyword in the subroutine call
Set Y to #&02 (the offset to the subroutine name - from the (&37-&38) base address). So, Y is the offset to
the first character of the subroutine name.
Call routine &9AF8 to check the variable name pointed to by (&37-&38) + Y. This routine reads the subroutine
name, and for each valid character - it increments X and Y. When an invalid character is found, the routine exits.
If Y is still #&02, after the check variable name routine has finished, then a valid subroutine name was not found
after the PROC/FN keyword - so issue 'Bad call' error.
Otherwise, Set the BASIC text pointer B offset (&1B) to the new X value (the offset pointing to the next character
after the end of the subroutine name) .
Call routine &8075 to lookup the subroutine name in the FN/PROC subroutine name table and to return with the
variable's address in (&2A-&2B) [if the variable was found].
If the zero flag is set then the subroutine name was not found in the lookup table, so jump to &AF97 to search for
the subroutine and create an entry for the subroutine name in the lookup table - if the subroutine was found (error if
not found). Jump to &B072 to call the subroutine (if found).
Otherwise, the subroutine name was found in the lookup table so jump to &B068 to call the subroutine.
|B017||169 164||A9 A4||LDA#&A4|
|B019||'||133 039||85 27||STA &27|
|B01E||e||101 004||65 04||ADC &04|
|B020||032 030 189||20 1E BD||JSR &BD1E Check for Stack clash with Heap|
|B024||146 004||92 04||STA (&04)|
|B026||160 000||A0 00||LDY#&00|
|B02A||189 000 001||BD 00 01||LDA &0100,X|
|B02D||145 004||91 04||STA (&04),Y|
|B02F||224 255||E0 FF||CPX#&FF|
|B031||208 245||D0 F5||BNE -11 --> &B028|
|B034||'||165 039||A5 27||LDA &27|
|B037||165 010||A5 0A||LDA &0A|
|B03A||165 011||A5 0B||LDA &0B|
|B03D||165 012||A5 0C||LDA &0C|
|B040||165 027||A5 1B||LDA &1B|
|B044||e||101 025||65 19||ADC &19|
|B046||164 026||A4 1A||LDY &1A|
|B048||144 002||90 02||BCC 2 --> &B04C|
|B04C||233 001||E9 01||SBC#&01|
|B04E||7||133 055||85 37||STA &37|
|B051||233 000||E9 00||SBC#&00|
|B053||8||133 056||85 38||STA &38|
|B055||160 002||A0 02||LDY#&02|
|B057||032 248 154||20 F8 9A||JSR &9AF8 Check Variable Name|
|B05A||192 002||C0 02||CPY#&02|
|B05C||240 174||F0 AE||BEQ -82 --> &B00C 'Bad call' error|
|B05E||134 027||86 1B||STX &1B|
|B060||u||032 117 128||20 75 80||JSR &8075 Lookup Subroutine Name in FN/PROC Variable Lookup Table|
|B063||208 003||D0 03||BNE 3 --> &B068 Call Subroutine|
|B065||L||076 151 175||4C 97 AF||JMP &AF97 Add Subroutine Name to FN/PROC Variable Lookup Table|