Small as64 tutorial
Due to the fact that I am used to programming in Turbo
Assembler, as64 has adopted it's syntax. Semicolons precedes
comment lines, high and low bytes of a label is extracted with
the > and < operators and bytes, words and ASCII-text is
marked with the .byte, .word
and .text keywords. The
things that differ is that constant mathematical expressions
aren't always correctly evaluated, labels can have an optional
trailing colon (this is since emacs indents lines with a colon
differently in asm-mode) and that as64 features a module system.
Constant expressions, like 2 + 3 * 4 or 4 * 3 + 2 are
not evaluated correctly. The operators have no
precedence over each other; instead expressions are evaluated
from left to right. For example, 1 + 2 * 3 is interpreted as
(1 + 2) * 3, which calculates as 9, and not the mathematically
correct 1 + (2 * 3), which is 7. This normally is not a
problem for me, as I seldom use any larger expressions, but
you should be very awary of this if you decide to use as64. Be
also aware that this might change in future versions, so
don't depend on this errorneous behaviour.
The modularity is achieved though the use of the keywords
module and export. Symbols (labels) can be
exported from each module
(typically a module consists of a file). The qualified keyword indicates that the
variable name should be preceeded by the module name. Let's
have a look at an example:
In the file reset.S you
find these statements:
;; reset.S
;;
;; functions for resetting the computer to normal c64-mode
module reset
export qualified all
reset:
sei
jsr $fda3
jsr $fd15
jsr $ff5b
cli
jmp $e397
error_reset:
sei
jsr $fda3
jsr $fd15
jsr $ff5b
cli
inc $d020
jmp $e397
First we see a few lines begining with a semicolon. These are
treated like a comment and are ignored by the assembler. (You
can use standard C-comments /* */ aswell.) After that a
module definition
comes. This is necessary if you want to export symbols qualified.
The next line contains the statement export qualified all which makes
all symbols to be exported with the module name preceding
them. In this case, the global symbol table would contain the
following entries:
reset.reset
reset.error_reset
Note that the export qualified
all keywords has to appear in that order. If they
don't, unexpected results might follow.
These qualified exported
symbols can be imported
into a local symbol table by using the keyword import. In this case, suppose a file
called boot.S includes the
following lines:
;; boot.S
;;
;; administers the bootup procedure of osT
;;
module boot
import reset
export qualified boot:
sei
jsr process.init
bcs boot_error
jsr malloc.init
bcs boot_error
jsr proctable.init
bcs boot_error
jsr zeropage.init
bcs boot_error
jsr scheduler.init
bcs boot_error
jsr process.add
cli
clc
rts
boot_error:
jmp error_reset
Here, the jmp error_reset
causes a jump to the error_reset subroutine that was
defined in reset.S. (Here,
it would not have been a good idea to import the modules process, malloc, proctable, zeropage
or scheduler, since they
all export an init-label. No warings are issued
if this would happen, and it would lead to unexpected results.)
Generally, it is not necessary, and is not recommended, to
import symbols from other modules. The reson for the import function to be included in
as64 is so that you can have a header file with definitions
for constant values, tables and such that you don't want to
have in the actual source file. Let's have a look at an
example:
The file process.h consists
of the following lines:
;; process.h
;;
;; defines constant values for process statuses etc
module process
export qualified all
DEAD = 0
RUNNING = 1
WAITING = 2
ZOMBIE = 3
STOPPED = 4
STARTING = 5
EXITING = 6
current .byte 0
next .byte 0
And in the file process.S
these lines are to be found:
;; process.S
;;
;; code for process control
module process
import process
export qualified getpid:
lda current
rts
Here, the lda current loads
the value from the current
defined in process.h. Other
modules (that doesn't import
process) refers to this address with process.current. The constants can
be used in a similar way, like lda
#process.RUNNING.
|