mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 00:29:31 +00:00
Explain more new stuff
git-svn-id: svn://svn.cc65.org/cc65/trunk@2715 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
140dee0eea
commit
35e639aac6
203
doc/ca65.sgml
203
doc/ca65.sgml
@ -800,22 +800,139 @@ id="scopesearch" name=""Scope search order"">).
|
||||
|
||||
<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>
|
||||
|
||||
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>
|
||||
|
||||
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>
|
||||
|
||||
|
||||
<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>
|
||||
|
||||
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
|
||||
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/
|
||||
instructions in 65816 mode and update the operand sizes accordingly. If
|
||||
the operand of such an instruction cannot be evaluated by the assembler
|
||||
(for example, because 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.
|
||||
In smart mode the assembler will do the following:
|
||||
|
||||
<itemize>
|
||||
<item>Track usage of the <tt/REP/ and <tt/SEP/ instructions in 65816 mode
|
||||
and update the operand sizes accordingly. If the operand of such an
|
||||
instruction cannot be evaluated by the assembler (for example, because
|
||||
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:
|
||||
|
||||
@ -2515,6 +2685,11 @@ Here's a list of all control commands and a description, what they do:
|
||||
.smart - ; Stop being smart
|
||||
</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>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user