Explain more new stuff
git-svn-id: svn://svn.cc65.org/cc65/trunk@2715 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
203
doc/ca65.sgml
203
doc/ca65.sgml
@@ -800,22 +800,139 @@ id="scopesearch" name=""Scope search order"">).
|
|||||||
|
|
||||||
<sect1>Structs, unions and enums<p>
|
<sect1>Structs, unions and enums<p>
|
||||||
|
|
||||||
|
Structs, unions and enums are explained in a <ref id="structs" name="separate
|
||||||
|
section">, I do only cover them here, because if they are declared with a
|
||||||
|
name, they open a nested scope, similar to <tt/<ref id=".SCOPE"
|
||||||
|
name=".SCOPE">/. However, when no name is specified, the behaviour is
|
||||||
|
different: In this case, no new scope will be opened, symbols declared within
|
||||||
|
a struct, union, or enum declaration will then be added to the enclosing scope
|
||||||
|
instead.
|
||||||
|
|
||||||
|
|
||||||
<sect1>Explicit scope specification<label id="scopesyntax"><p>
|
<sect1>Explicit scope specification<label id="scopesyntax"><p>
|
||||||
|
|
||||||
|
Accessing symbols from other scopes is possible by using an explicit scope
|
||||||
|
specification, provided that the scope where the symbol lives in has a name.
|
||||||
|
The namespace token (<tt/::/) is used to access other scopes:
|
||||||
|
|
||||||
|
<tscreen><verb>
|
||||||
|
.scope foo
|
||||||
|
bar: .word 0
|
||||||
|
.endscope
|
||||||
|
|
||||||
|
...
|
||||||
|
lda foo::bar ; Access foo in scope bar
|
||||||
|
</verb></tscreen>
|
||||||
|
|
||||||
|
The only way to deny access to a scope from the outside is to declare a scope
|
||||||
|
without a name (using the <tt/<ref id=".SCOPE" name=".SCOPE">/ command).
|
||||||
|
|
||||||
|
A special syntax is used to specify the global scope: If a symbol or scope is
|
||||||
|
preceeded by the namespace token, the global scope is searched:
|
||||||
|
|
||||||
|
<tscreen><verb>
|
||||||
|
bar = 3
|
||||||
|
|
||||||
|
.scope foo
|
||||||
|
bar = 2
|
||||||
|
lda #::bar ; Access the global bar (which is 3)
|
||||||
|
.endscope
|
||||||
|
</verb></tscreen>
|
||||||
|
|
||||||
|
|
||||||
<sect1>Scope search order<label id="scopesearch"><p>
|
<sect1>Scope search order<label id="scopesearch"><p>
|
||||||
|
|
||||||
|
The assembler searches for a scope in a similar way as for a symbol. First, it
|
||||||
|
looks in the current scope, and then it walks up the enclosing scopes until
|
||||||
|
the scope is found.
|
||||||
|
|
||||||
|
However, one important thing to note when using explicit scope syntax is, that
|
||||||
|
a symbol may be accessed before it is defined, but a scope may <bf/not/ be
|
||||||
|
used without a preceeding definition. This means that in the following
|
||||||
|
example:
|
||||||
|
|
||||||
|
<tscreen><verb>
|
||||||
|
.scope foo
|
||||||
|
bar = 3
|
||||||
|
.endscope
|
||||||
|
|
||||||
|
.scope outer
|
||||||
|
lda #foo::bar ; Will load 3, not 2!
|
||||||
|
.scope foo
|
||||||
|
bar = 2
|
||||||
|
.endscope
|
||||||
|
.endscope
|
||||||
|
</verb></tscreen>
|
||||||
|
|
||||||
|
the reference to the scope <tt/foo/ will use the global scope, and not the
|
||||||
|
local one, because the local one is not visible at the point where it is
|
||||||
|
referenced.
|
||||||
|
|
||||||
|
Things get more complex if a complete chain of scopes is specified:
|
||||||
|
|
||||||
|
<tscreen><verb>
|
||||||
|
.scope foo
|
||||||
|
.scope outer
|
||||||
|
.scope inner
|
||||||
|
bar = 1
|
||||||
|
.endscope
|
||||||
|
.endscope
|
||||||
|
.scope another
|
||||||
|
.scope nested
|
||||||
|
lda #outer::inner::bar ; 1
|
||||||
|
.endscope
|
||||||
|
.endscope
|
||||||
|
.endscope
|
||||||
|
|
||||||
|
.scope outer
|
||||||
|
.scope inner
|
||||||
|
bar = 2
|
||||||
|
.endscope
|
||||||
|
.endscope
|
||||||
|
</verb></tscreen>
|
||||||
|
|
||||||
|
When <tt/outer::inner::bar/ is referenced in the <tt/lda/ instruction, the
|
||||||
|
assembler will first search in the local scope for a scope named <tt/outer/.
|
||||||
|
Since none is found, the enclosing scope (<tt/another/) is checked. There is
|
||||||
|
still no scope named <tt/outer/, so scope <tt/foo/ is checked, and finally
|
||||||
|
scope <tt/outer/ is found. Within this scope, <tt/inner/ is searched, and in
|
||||||
|
this scope, the assembler looks for a symbol named <tt/bar/.
|
||||||
|
|
||||||
|
Please note that once the anchor scope is found, all following scopes
|
||||||
|
(<tt/inner/ in this case) are expected to be found exactly in this scope. The
|
||||||
|
assembler will search the scope tree only for the first scope (if it is not
|
||||||
|
anchored in the root scope). Starting from there on, there is no flexibility,
|
||||||
|
so if the scope named <tt/outer/ found by the assembler does not contain a
|
||||||
|
scope named <tt/inner/, this would be an error, even if such a pair does exist
|
||||||
|
(one level up in global scope).
|
||||||
|
|
||||||
|
Ambiguities that may be introduced by this search algorithm may be removed by
|
||||||
|
anchoring the scope specification in the global scope. In the example above,
|
||||||
|
if you want to access the "other" symbol <tt/bar/, you would have to write:
|
||||||
|
|
||||||
|
<tscreen><verb>
|
||||||
|
.scope foo
|
||||||
|
.scope outer
|
||||||
|
.scope inner
|
||||||
|
bar = 1
|
||||||
|
.endscope
|
||||||
|
.endscope
|
||||||
|
.scope another
|
||||||
|
.scope nested
|
||||||
|
lda #::outer::inner::bar ; 2
|
||||||
|
.endscope
|
||||||
|
.endscope
|
||||||
|
.endscope
|
||||||
|
|
||||||
|
.scope outer
|
||||||
|
.scope inner
|
||||||
|
bar = 2
|
||||||
|
.endscope
|
||||||
|
.endscope
|
||||||
|
</verb></tscreen>
|
||||||
|
|
||||||
|
|
||||||
|
<sect>Address sizes<label id="address-sizes"><p>
|
||||||
<sect>Address sizes<label id="address-sizes">
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -2493,6 +2610,51 @@ Here's a list of all control commands and a description, what they do:
|
|||||||
<tt><ref id=".PSC02" name=".PSC02"></tt>
|
<tt><ref id=".PSC02" name=".PSC02"></tt>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1><tt>.SIZEOF</tt><label id=".SIZEOF"><p>
|
||||||
|
|
||||||
|
<tt/.SIZEOF/ is a pseudo function that returns the size of its argument. The
|
||||||
|
argument can be a struct/union, a struct member, a procedure, or a label. In
|
||||||
|
case of a procedure or label, its size is defined by the amount of data
|
||||||
|
placed in the segment where the label is relative to. If a line of code
|
||||||
|
switches segments (for example in a macro) data placed in other segments
|
||||||
|
does not count for the size.
|
||||||
|
|
||||||
|
Please note that a symbol or scope must exist, before it is used together with
|
||||||
|
<tt/.SIZEOF/ (this may get relaxed later, but will always be true for scopes).
|
||||||
|
A scope has preference over a symbol with the same name, so if the last part
|
||||||
|
of a name represents both, a scope and a symbol, the scope is choosen over the
|
||||||
|
symbol.
|
||||||
|
|
||||||
|
Usage examples:
|
||||||
|
|
||||||
|
<tscreen><verb>
|
||||||
|
.struct Point ; Struct size = 4
|
||||||
|
xcoord .word
|
||||||
|
xcoord .word
|
||||||
|
.endstruct
|
||||||
|
|
||||||
|
P: .tag Point ; Declare a point
|
||||||
|
|
||||||
|
.code
|
||||||
|
.proc Code ; 3 bytes
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
.proc Data ; 4 bytes
|
||||||
|
.data ; Segment switch!!!
|
||||||
|
.res 4
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
lda #.sizeof(Point) ; Loads 4
|
||||||
|
lda #.sizeof(Point::xcoord) ; Loads 2
|
||||||
|
lda #.sizeof(P) ; Loads 4
|
||||||
|
lda #.sizeof(Code) ; Loads 3
|
||||||
|
lda #.sizeof(Data) ; Loads 0
|
||||||
|
</verb></tscreen>
|
||||||
|
|
||||||
|
|
||||||
<sect1><tt>.SMART</tt><label id=".SMART"><p>
|
<sect1><tt>.SMART</tt><label id=".SMART"><p>
|
||||||
|
|
||||||
Switch on or off smart mode. The command must be followed by a '+' or
|
Switch on or off smart mode. The command must be followed by a '+' or
|
||||||
@@ -2500,13 +2662,21 @@ Here's a list of all control commands and a description, what they do:
|
|||||||
is off (that is, the assembler doesn't try to be smart), but this
|
is off (that is, the assembler doesn't try to be smart), but this
|
||||||
default may be changed by the -s switch on the command line.
|
default may be changed by the -s switch on the command line.
|
||||||
|
|
||||||
In smart mode the assembler will track usage of the <tt/REP/ and <tt/SEP/
|
In smart mode the assembler will do the following:
|
||||||
instructions in 65816 mode and update the operand sizes accordingly. If
|
|
||||||
the operand of such an instruction cannot be evaluated by the assembler
|
<itemize>
|
||||||
(for example, because the operand is an imported symbol), a warning is
|
<item>Track usage of the <tt/REP/ and <tt/SEP/ instructions in 65816 mode
|
||||||
issued. Beware: Since the assembler cannot trace the execution flow this
|
and update the operand sizes accordingly. If the operand of such an
|
||||||
may lead to false results in some cases. If in doubt, use the <tt/.Inn/ and
|
instruction cannot be evaluated by the assembler (for example, because
|
||||||
<tt/.Ann/ instructions to tell the assembler about the current settings.
|
the operand is an imported symbol), a warning is issued. Beware: Since
|
||||||
|
the assembler cannot trace the execution flow this may lead to false
|
||||||
|
results in some cases. If in doubt, use the <tt/.Inn/ and <tt/.Ann/
|
||||||
|
instructions to tell the assembler about the current settings.
|
||||||
|
<item>In 65816 mode, replace a <tt/RTS/ instruction by <tt/RTL/ if it is
|
||||||
|
used within a procedure declared as <tt/far/, or if the procedure has
|
||||||
|
no explicit address specification, but it is <tt/far/ because of the
|
||||||
|
memory model used.
|
||||||
|
</itemize>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@@ -2515,6 +2685,11 @@ Here's a list of all control commands and a description, what they do:
|
|||||||
.smart - ; Stop being smart
|
.smart - ; Stop being smart
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
|
See: <tt><ref id=".A16" name=".A16"></tt>,
|
||||||
|
<tt><ref id=".A8" name=".A8"></tt>,
|
||||||
|
<tt><ref id=".I16" name=".I16"></tt>,
|
||||||
|
<tt><ref id=".I8" name=".I8"></tt>
|
||||||
|
|
||||||
|
|
||||||
<sect1><tt>.STRAT</tt><label id=".STRAT"><p>
|
<sect1><tt>.STRAT</tt><label id=".STRAT"><p>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user