Assembler : Usage

Command Line :

PCEAS [-options] [-? (for help)] infile[.ASM]

The assembler accepts only one input file 'infile', that will be assembled into a ROM file (*.PCE), directly loadable by an emulator. The size limit for a ROM is 1 MB.

A listing file can also be generated (*.LST) if the LIST directive is encountered in the input file.

Here's a description of the different options :

Option : Description :

-s
-S

Show segment usage. If one of those options is specified the assembler will display informations on the ROM bank usage. Use '-s' to show basic informations and '-S' to show more detailled informations.

-l #

Control the listing file output :

0 - disable completely the generation of the listing file even if the LIST directive is used in the input file
1 - minimun level; code produced by DB, DW, DEFPAL, DEFCHR and DEFSPR will not be dumped
2 - normal level; only code produced by DEFPAL, DEFCHR and DEFSPR will not be dumped
3 - maximun level; all the code is dumped in the listing file

The default level is level 2.

-m

Force macros expansion in the listing file, even if the MLIST directive is not seen in the input file.

-raw Control the header generation. By default the assembler always adds an header to the ROM file; unless '-raw' is specified, in this case no ROM header is generated.

-dev sorry, not yet documented

-mx sorry, not yet documented

-srec sorry, not yet documented

-cd
-scd
sorry, not yet documented

Include path :

By default the assembler looks in the current directory when loading an include file, but when it doesn't find the file it then uses the environmental variable 'PCE_INCLUDE' to get a list of include paths.

Ideally, you will want to set this variable in your 'AUTOEXEC.BAT' file, and have it point to the 'INCLUDE' directory of MagicKit. Like this :


 set PCE_INCLUDE=c:\magickit\include

Symbols :

Two types of symbol are supported, global symbols and local symbols. Local symbols are preceded by a dot '.' and are valid only between two global symbols. A symbol can be followed by a colon ':' but this is not necessary.

Expressions :

The assembler supports very complex expressions. You can use as many level of parenthesis as you want and spaces between operators and numbers are possible.

Numbers can be written in three bases : hexadecimal ($7F), binary (%0101) and decimal (48). Character values are also supported ('A').

All the usual operators are present :

+, -, *, /, %, ^, &, |, ~, <<, >>

As well as the comparison operators :

=, !=, !, <, >, <=, >=

For the priority, the same rules as C apply.

You can also use predefined or user-defined functions in an expression.

Predefined functions :

HIGH(expr) - Returns the high byte of a value.

LOW(expr) - Returns the low byte of a value.

BANK(label) - Returns the bank index of a label.

PAGE(label) - Returns the page index of a label.

VRAM(label) - Returns the VRAM address of a label (if defined).

PAL(label) - Returns the default palette of a label (if defined).

SIZEOF(label) - sorry, not yet documented

User-defined functions :

User-defined functions are declared with the FUNC directive :


 BATVAL    .func ((\1) << 12) | ((\2) >> 4)

Up to nine arguments, \1 to \9, can be used.

To call a function simply enclose arguments within parenthesis and separate them with a comma :


           stw   #BATVAL(4, $1000), <chr

User-defined functions can be very useful, one often needs to use the same calculation again and again in expressions. Defining a function will save you a lot of work, and help reduce typo errors. :)

Note that function calls can be nested, you can call one function from another without any problem, however, recursive calls will produce an error.

Macros :

While functions are very useful to replace common expressions by just a function call, macros are used to replace common groups of instructions by a single line of code.

You start a macro definition with :


 label     .macro

Or you can also place the label after the MACRO keyword, like this :


           .macro label 

After comes the body of the macro, which is terminated by the ENDM directive.

As an example let's define a 'neg' macro to negate the accumulator.


 neg       .macro
            eor   #$FF
            inc   A
           .endm

Macros can also have parameters. In the macro body you refer to a parameter by using the backslash character ('\') followed by a digit. Nine parameters can be used, \1 to \9.

Here's another example:


 add       .macro       ; add a value to register A
            clc         ; (handle carry flag)
            adc   \1
           .endm

More "special" parameters can be used, here's a list of all the possible parameters you can use inside a macro :

Parameter : Description :

\1 - \9 Input parameter - up to nine can be used in a macro call.

\# Number of input parameters.

\?1 - \?9 Returns 'type' of input parameter:

ARG_NONE = no argument
ARG_REG = register
(A, X, Y)
ARG_IMMED = Immediate data type
(#$xx)
ARG_ABSOLUTE = Absolute addressing
(label or $xxxx)
ARG_INDIRECT = Indirect addressing
([label])
ARG_STRING = String argument
("...")
ARG_LABEL = Label

\@ Special parameter that returns a different number for each macro call; it's often used to define local symbols inside macros :


 abs       .macro
            lda   \1
            bpl   .x\@
            eor   #$FF
            inc   A
            sta   \1
 .x\@:
           .endm