8-Bit Software

The BBC and Master Computer Public Domain Library

Back to 8BS Or Back to Disassembly

Page Last Altered:

B017 FN

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.

Disassembly for the FN routine

B017   169 164 A9 A4 LDA#&A4
B019 ' 133 039 85 27 STA &27
B01B   186 BA TSX
B01C   138 8A TXA
B01D   024 18 CLC
B01E e 101 004 65 04 ADC &04
B020   032 030 189 20 1E BD JSR &BD1E Check for Stack clash with Heap
B023   138 8A TXA
B024   146 004 92 04 STA (&04)
B026   160 000 A0 00 LDY#&00
B028   232 E8 INX
B029   200 C8 INY
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
B033   154 9A TXS
B034 ' 165 039 A5 27 LDA &27
B036 H 072 48 PHA
B037   165 010 A5 0A LDA &0A
B039 H 072 48 PHA
B03A   165 011 A5 0B LDA &0B
B03C H 072 48 PHA
B03D   165 012 A5 0C LDA &0C
B03F H 072 48 PHA
B040   165 027 A5 1B LDA &1B
B042   170 AA TAX
B043   024 18 CLC
B044 e 101 025 65 19 ADC &19
B046   164 026 A4 1A LDY &1A
B048   144 002 90 02 BCC 2 --> &B04C
B04A   200 C8 INY
B04B   024 18 CLC
B04C   233 001 E9 01 SBC#&01
B04E 7 133 055 85 37 STA &37
B050   152 98 TYA
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


 Back to 8BS