as64 - A cross-assembler for the 6510 CPU


as64 is a two pass cross-assembler for 6510 CPU systems, mainly the Commodore 64. as64 is free software and is licensed under the GNU General Public License (GPL).

Version 0.9 of as64 is avaliable for download:

as64 has been tested and run on GNU/Linux and FreeBSD. Moreover, as64 0.9 is quite stable and works fine for me, but if you encounter a bug, send me an email about it and I will see what I can do.

I once wrote a short as64 tutorial:

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.

$Date: 2002/07/20 10:04:20 $


Main menu
TFE | Music | as64 ]
Table layout version
Printer friendly version

© Copyright Adam Dunkels 2001-2003