BBC BASIC Programming Techniques - Conditional Assembly Macros ============================================================== J.G.Harston, 02-Nov-1996 The following assembly macros allow you to do conditional assembly with the BASIC assembler. DEFFNif(A%):IFA%:z%=0:=opt% ELSE z%=P%:=opt%AND-2 DEFFNendif:IFz%:z%=P%-z%:P%=P%-z%:O%=O%-z%:=opt% ELSE =opt% DEFFNelse:IFz%:z%=P%-z%:P%=P%-z%:O%=O%-z%:z%=0:=opt% ELSE z%=P%:=opt%AND-2 They are used in assembler source by calling them with OPT as with any other assembler macro, as in the following example: DEBUG%=TRUE FOR opt%=4 TO 7 STEP 3 P%=load%:O%=code% [OPT opt% ... OPT FNif(DEBUG%) JSR debug_code OPT FNendif ... ]NEXT The functions rely on you using opt% to hold the assembly option, and uses variable z%, which must not by changed by the rest of the source program. Any assembly listing for the excluded section is turned off. Programming considerations -------------------------- The if/else/endif works by assembling the code, then backtracking if the condition is FALSE. Consequently, there are some limitations which must be born in mind. The if/else/endif cannot be nested. Labels within an if/else block must be different to those in an else/endif block, otherwise the assembler will get confused with forward references. For instance, use this type of coding: OPT FNif(PUSHWS%) LDY #0 .CheckLp1 LDA (zp),Y ... INY:BNE CheckLp1 OPT FNelse .CheckLp2 LDY #0:LDA (zp),Y:TAY ... INC zp+0:BNE CheckLp2 INC zp+1:BNE CheckLp2 OPT FNendif If both conditional blocks used the same label for the loop, on the second pass the first block would use the definition set in the second block. Because unwanted code is assembled and then backtracked over, if there is a conditional block right at the end of your assembly you must make sure there is enough space for this in the memory you are assembling to. For example, the following continues assembling, then moves back before finishing, so you must ensure the memory at O% will allow this ... OPT FNif(TAILDATA%) EQUS "Data and end of code" OPT FNendif ]:NEXT opt% Another way of calling macros is to use EQUS as this does not rely on the assembly option being in opt%. The following are versions of the if/else/endif functions that can be used this way. However, the assembly listing is not turned off for the disabled section. DEFFNif(A%):IFA%:z%=0:="" ELSE z%=P%:="" DEFFNendif:IFz%:z%=P%-z%:P%=P%-z%:O%=O%-z%:="" ELSE ="" DEFFNelse:IFz%:z%=P%-z%:P%=P%-z%:O%=O%-z%:z%=0:="" ELSE z%=P%:="" You would use them in this manner: DEBUG%=TRUE FOR pass%=4 TO 7 STEP 3 P%=load%:O%=code% [OPT pass% ... EQUS FNif(DEBUG%) JSR debug_code EQUS FNendif ... ]NEXT