Topic : The GFA-Basic Compendium
Author : GFA Systemtechnik GmbH
Version : GFABasic.HYP v2.98 (12/31/2023)
Subject : Documentation/Programming
Nodes : 899
Index Size : 28056
HCP-Version : 3
Compiled on : Atari
@charset : atarist
@lang :
@default : Document not found
@help : Help
@options : +g -i -s +z
@width : 75
@hostname : STRNGSRV
@hostname : CAB
@hostname : HIGHWIRE
@hostname : THING
View Ref-FileAssembler and GFABASIC
by
Rev 4 3/16/2018
_________________________________
There are thee commands for calling subroutines written in assembler. Each
command has its pros and cons and you will have to decide which one fits your
needs. This chart may help:
Command Saves a3-a6 Parameter size(s) Returns a value
C:() Optional Words/Longs Yes
CALL Optional Longs No
RCALL Always Longs via array Yes via array
The most critical thing involved with calling assembler is the contents of
registers a3-a6 since these are used internally by GFABASIC itself. Obviously
you don't want to mess up a7 either since that's the stack. By default compiled
code does not save and restore these registers, but that's easily changed with
the $C+ compiler option.
In some cases you will be forced to use $C+, either because you didn't code the
assembler part yourself, or you don't have the skill to recode the assembler
listing. It's also possible you are calling a shared library that uses these
registers.
If a3-a6 are destroyed the symptoms can be just about anything. It might
freezing up, issue strange error messages that make no sense, or outright
crash. If you add the compiler option $C+ and the problem(s) goes away, you
probably solved it.
_______________________________________________________________________________
So how do I use this $C+ compiler command? There's actually two forms of this
compiler option and they only work with C:() and CALL:
$C+ !turn on a3-a6 register saving
$C- !turn off a3-a6 register saving
If your assembler routine never touches a3-a6 you don't have to do anything. In
fact avoiding $C+ will speed up the program. The default state of the compiler
is $C- (off).
If you only have one assembler subroutine it's as simple as putting $C+ at the
top of your listing since its treated like a global. Any use of C:() or CALL
throughout the program will automatically save and restore a3-a6.
If by some chance you have two assembler subroutines and only one clobbers some
critical register then placing the compiler option before each call is probably
the best way.
$C-
result%=C:asm1%() !does not touch a3-a6
'
$C+ !option on
result%=C:asm2%() !clobbers some critical register
_______________________________________________________________________________
Other things to remember:
Parameters must be passed on the stack, thus if calling a 'C' function one must
use the cdecl parameter passing method. By default parameters passed using C:()
are treated as word size unless one uses the L: function. Example:
result%=C:asm_adr%(1,2,L:3,L:buf_adr%)
In the interpreter registers a3-a6 are always saved and restored regardless of
which command is used.
Note: CALL is completely broken in the original interpreter, but fixed in the
updated one.