Difference between revisions of "Global control block"
Revision as of 01:59, 8 March 2015
When calling MOS functions from BASIC you often need to pass a control block pointed to by X% and Y%. A common method of doing this is to use code similar to:
DIM ctrl% 31 : DEFPROCgbpb(in%,addr%,num%) LOCAL A%,X%,Y% ?ctrl%=in% ctrl%!1=addr% ctrl%!5=num% X%=ctrl% AND 255 Y%=ctrl% DIV 256 A%=2 CALL &FFD1 ENDPROC
Doing this involves setting X% and Y% every time a MOS routine is called. A neater and more compact method is to use X% to point to the control block instead of the control block name itself:
DIM ctrl% 31:X%=ctrl%:Y%=X% DIV 256 : ?X%=in% X%!1=addr% X%!5=num% A%=2:CALL &FFF1
This has several advantages. It removes all the repetitions of X%=ctrl% AND 255:Y%=ctrl% DIV 256 and LOCAL X%,Y% inside procedure and functions; and indexing into the control block with X% is more compact and neater. Additionally, with X% holding the whole address of the control block, and not just the bottom 8 bits, ensures that when running versions of BASIC with more than 64K of memory (such as 32016, ARM, 80x86) the control block is passed to the MOS call wherever it is in memory, not just in the first 64K of memory. (If X% is less than 256, BBC BASIC V looks for higher-order parts of the address in Y%, for compatibility with the usual expressions.)
X% and Y% should be set at the start of the program and at the start of any main program loop. Otherwise, any calls to OSBYTE may overwrite the values in X% and Y% if an error occurs. Use code constructed similar to the following:
DIM ctrl% 31:X%=ctrl%:Y%=X%DIV256 ON ERROR IF FNerr:PROCexit(ERR):END REPEAT:X%=ctrl%:Y%=X%DIV256
All the BASIC libraries at [mdfs.net] expect X% and Y% to point to a global control block in this way.
By JGH, Jun-2007