Assembler, led astray


A disgruntled customer enters the shop, carrying a chainsaw.

Customer (angry): "Bought this thing yesterday. It took me eight hours to cut down one stupid tree."
Salesman (confused): "Let me see.", grabs the chainsaw, and starts the motor.
Chainsaw: "BRRMMMM..."
Customer (perplexed): "What's that noise ?"

If in doubt when using a new tool, read the manual.


For the next example, we use the AS macroassembler,
that can be downloaded for free.
One last warning.
When comparing assemblers, language syntax and options/directives
may look different.
Even if they all support the same processor.
Some assemblers are case sensitive, some are not.
Some complain if there is no ':' after a label, some complain if
there is one, and the rest just ignores such things.
Some expect 0x55 to be a hexadecimal value, others may call it $55.
Some insist that numbers starting without '$' or '0x' are decimal,
some may take it as a hexadecimal value by default.
Take care.

It is strongly recommended to read the manual before starting
any experiments...
unlike as some customers seem to do with chainsaws.


Now here some sourcecode.

        ;traf1.asm

        CPU     68000
        PADDING OFF

;-------------------------------------------------------

R1      EQU     $01
Y1      EQU     $02
G1      EQU     $04

R2      EQU     $08
Y2      EQU     $10
G2      EQU     $20

AGAIN   EQU     $80

;-------------------------------------------------------

SEQ1    MACRO                                      
        DC.B    R2 |      G1              ;2 red, 1 green
        DC.B    R2 |      G1              ;
        DC.B    R2 |      G1              ;
        DC.B    R2 |      Y1              ;
        DC.B    R2 | Y2 | R1              ;
        DC.B    G2 |      R1              ;
        DC.B    G2 |      R1              ;
        DC.B    G2 |      R1              ;
        DC.B    Y2 |      R1              ;
        DC.B    R2 |      R1 | Y1 | AGAIN ;start again
        ENDM

;-------------------------------------------------------

        ORG     $0000
        SEQ1

;-------------------------------------------------------

        END

Now to explain it.

AS supports different processors/CPUs, and syntax/options/directives
may vary.
To be on the safe side, we select 68000.

Oops, something went wrong: we got 20 Bytes instead of 10.
The Bytes we wanted to have are placed at even addresses, odd addresses
are filled with zero.
After some hours of digging through manuals, we may figure out that 68000
machine code has a length of (multiples of) 16 Bit, starting at an even
address.
For the assembler it's obvious, and it automatically fills Bytes at odd
addresses with zero,
without that we are neither asked nor informed about it...
unless we turn PADDING OFF.

A semi-colon tells the assembler, that the rest of the line is a comment,
and should be ignored.

Then we say, that R1 EQUals $01, Y1 equals $02, and G1 equals $04.
We are talking here about red,yellow,green for the first traffic light.
You should know, what R2,Y2 and G2 are good for.
AGAIN is equal to $80, what we used in the last line of our table to reset
the counter to zero... to start again.
Would be better to write some comments behind those definitions...
just do it.

The assembler recognizes that SEQ1 is meant to be a macro.
What means, any SEQ1 that shows up later in the sourcecode will be
automatically "replaced" with the lines between MACRO and ENDM,
in that case 10 lines of 'DC.B'.
DC.B Defines Constants with the size of one Byte.
We take R2 (defined as $08), perform a logical OR with G1 (defined as $04),
what will give us $0c as result.
Note, that we are only defining a macro. The assembler doesn't generate
any Bytes at that point.

Now that we are through with our definitions, we use ORG to set the
origin of our "program" to $0000.

And now, the miracle happens. The assembler recognizes SEQ1 as a
defined macro, is still aware
of all the Bits we defined before, and
generates 10 Bytes of constants.

So far, we have reached the END.


When the hardware changes, for instance the green LED from traffic light 2
is now connected to O6 of the EPROM,
we only have to change our definition of G2:

G2      EQU     $40

Changing the length/function of the phases is now only a matter of cut/copy/paste.
We also can recognize very fast, what this "program" does, without consulting
the schematic.
But we pay for that with a higher level of complexity, and we have to read
the manual from time to time.

And never forget: our hardware only supports tables with a maximum
of 16 entries (counting from 0..15).

From what we have learned, we can generate long sequences of Bytes,
but anything beyound/above address $000f won't make it to the LEDs...
unless we use two 74163 for counting, what would set the maximum
to 256 entries, or $00ff.


To generate a listing and a binary file from traf1.asm with AS:

as    traf1.asm /xLn
p2bin traf1
Hint: better make backups of your source code from time to time.
It's also a good thing, to check consistence between what you see
in your source code, and what you finally get in the assembler
output listings and the resulting binary files.

Avoid naming your constants/labels/macros like assembler directives
or processor opcodes.
Also avoid accidentally giving a label and a macro the same name.
The assembler could become confused enough to produce garbage
without that we are warned/informed about it.


[HOME] [UP]/ [BACK] [1] [2] [3] [4] [5] [6] [7] [8] [NEXT]

(c) Dieter Mueller 2005