6809 Assembly Language Programming on the TRS-80
Color Computer
(Using M.E.S.S. as the Vehicle)
By: Robert ([email protected])
Okay, since you have apparently decided to take this
journey with me, I will try to make it as painless as possible (and hopefully,
I won't be quite so annoying).
To begin with, I needed a project. Something simple to practice coding
the 6809. I thought about it and decided that I would do something with
the 32x16 text screen. After some thought, I decided I would like to have
the screen cleared to black. Then, I would like to have a border around
the screen, comprised of all eight solid color blocks that the CoCo is
capable of generating. Just to make it interesting, I thought I would like
to have this border rotating counter-clockwise. That should be enough of
a project to get started, but I thought perhaps, I would add another border
under the other, but have it rotating clock-wise, and finally, I would
like to put a text window in the center of the screen, with scrolling text
(something like 6 lines or so), and finally, have the routine continually
checking the keyboard for a keypress at which point, the routine will return
control to BASIC.
So, here we are, ready to create our little routine, which could possibly
be used as an intro screen for BASIC programs. I would like to hear suggestions
of other possible uses for the routine. This is, of course, assuming my
efforts will be successful (they will <grin>). Okay, so to begin, I
need the character codes for the block graphics characters that I intend
to use to create the border. Not having the CoCo manual readily accessible,
I fired up the emulator and entered in the following BASIC program:
10 FOR F=0 TO 255
20 PRINT CHR$(F);HEX$(F);" ";
30 NEXT F
Upon typing RUN and pressing [ENTER], the entire CoCo character set
scrolled happily by, doing me absolutely no good. So, RUNning the program
again and being quick enough to use the CoCo's [SHIFT][@] key sequence
to pause program execution, I was able to acquire the needed information,
as follows:
COLOR OF SOLID BLOCK CHARACTER |
HEXADECIMAL CODE FOR THAT CHARACTER |
BLACK (ABSENCE OF COLOR) |
$80, $90, $A0, $B0, $C0, $D0, $E0, $F0 |
GREEN |
$8F |
YELLOW |
$9F |
BLUE |
$AF |
RED |
$BF |
BUFF |
$CF |
CYAN |
$DF |
MAGENTA |
$EF |
ORANGE |
$FF |
Mind you, had I not remembered the CoCo's color designations, I would
have listed BUFF as WHITE, CYAN as LIGHT BLUE and MAGENTA as PURPLE. The
fact that I did remember this might mean that there is hope of me remembering
all that I used to know about 6809 Assembly Programming. You may note above
that there are EIGHT hexadecimal codes that produce black. However, $80
is the official code for black. The other codes are for the other colors
listed in the chart above, but represent absence of color, thus we get
black.
Note that each solid block of color is exactly $20 (I will be speaking
hexadecimal for the entirety of this - my appologies) higher than the color
block that precedes it. This may make things easier down the line (instead
of sticking the character data in a table, we can start at $8F, display
that character, increment by $20, display the next character and so on).
Of course, I might still use a table - I haven't got that far yet, so we'll
see.
Also, creating and maintaining this document will be on an ''As I Have
Time'' Basis, so if it goes days without an update, please don't FLAME
me. I have to work on it when I am not at work, not sleeping, etc.
Now, let's have a look at how we intend to clear the 32x16 screen to
black (this is an easy one):
Here is the Assembly Language Listing (In Disk EDTASM+ Lingo):
00100 ORG
$4000
00110 *PRESERVE REGISTERS
00120 START PSHS
A,B,X,Y,U,CC
00130 *POINT TO START OF SCREEN
00140 LDX
#$0400
00150 *BLACK BLOCK = $80
00160 LDA
#$80
00170 *PUT BLOCK ON SCREEN & INCREMENT POINTER
00180 LOOP STA
,X+
00190 *CHECK FOR END OF SCREEN
00200 CMPX
#$0600
00210 *NOT END OF SCREEN, SO DO AGAIN
00220 BNE
LOOP
00230 *RESTORE REGISTERS AND RETURN (PULS PC PERFORMS LIKE RTS)
00240 PULS
CC,U,Y,X,B,A,PC
00250 END
Note that the above listing is not spaced exactly as it will appear
on your CoCo's screen. You would enter it as:
00120 (the editor automatically displays the line number), followed
by START, then [LEFT ARROW], PSHS, [LEFT ARROW], A,B,X,Y,U,CC followed
by [ENTER], but hopefully you will already be familiar with EDTASM, or
the Editor/Assembler that you happen to be using. Throughout this document,
I will be referring to the commands and procedures of Disk EDTASM+, so
you will have to be familiar with your Assembler in order to use this with
something other than Disk EDTASM+.
Line 00100 tells the assembler the starting address in memory of this
routine.
Line 00110 is a comment (think REM statement)
Line 00120 Preserves the contents of all of the CPU's registers upon
entering this routine by pushing them onto the stack (as pointed to by
the S register). Although this may not be necessary, it doesn't hurt either.
If the routine used to call this routine needs the contents of the registers
to be as they were prior to this routine, then this would be a necessary
step. However, since this routine only modifies the X, A and CC registers,
we could have just used: PSHS A,X,CC.
Line 00130 is a comment.
Line 00140 loads the value $0400 into the index register X (this is
the IMMEDIATE addressing mode). $0400 is the normal starting address in
memory of the 32x16 VDG text screen, the end of which is $05FF.
Line 00150 is a comment.
Line 00160 loads the value $80 into the Accumulator A (also IMMEDIATE
ADDRESSING MODE). This is the character code for the solid black block.
Line 00170 is a comment.
Line 00180 places the contents of ACCA (Accumulator A) into the address
contained in the Index Register X, and automatically increments the X register
by 1.
Line 00190 is a comment.
Line 00200 compares the contents of the Index Register X with the number
$0600. Recall that $05FF is the end of the screen, therefore if X has incremented
to $0600, then we have finished filling the screen with black blocks ($80).
Line 00210 is a comment.
Line 00220 branches back to Line 00180 if we have not reached the end
of the screen, otherwise, we fall through to the next instruction.
Line 00230 is a comment.
Line 00240 retrieves the register values from the stack that we pushed
there at the beginning of this routine. Notice I have added the PC register
to the PULS. This pulls the Program Counter from the stack and functions
just like RTS, thereby saving the need of including the RTS instruction
to return from this routine.
Line 00250 Tells the assembler that this is the end of the Assembly
Language Listing.
In the future, I will try not to be so long winded - for example, you
will no longer see Line xxxxx is a comment. Only the actually Instructions
will be broken down for you. Okay, so enter the above program into Disk
EDTASM+ and save it to disk via: WD SCREEN
Then, assemble it by entering AD SCREEN /AO
This will assemble the program to disk using the Absolute Origin Switch
of Edtasm.
Exit Edtasm and return to BASIC.
Type: CLEAR 300,&H3FFF
LOADM "SCREEN"
EXEC &H4000
You should get a nice black screen, with the OK prompt of BASIC returning
and ruining the effect, but at least you can see that it works.
This is all that I have time for this wonderful Easter Day, but I promise
to continue soon and we'll work on creating the rotating borders. Hopefully
this will be fun to you folks that are wanting to learn assembly. The already
Assembly Guru's will no doubt be bored! Until Next Time..... Robert
|
UPDATE
(COURTESY OF ROBERT GAULT)
Subject: Re: journal for 6809 assembly
From: Robert Gault <e-mail address removed to foil spam-bots>
Date: Sun, Apr 08, 2007 4:10 pm
To: [email protected]
Hi Robert,
Here is some information that should help you. On the 32 character text
screen there are 16 patterns and 8 colors. The formula is code =128+16(c-1)+pattern
where c is color.
Basic automatically pushes all the registers when you execute an ml
program so it is not necessary to start your program with pshs
d,x,y,u,cc and end it with
puls d,x,y,u,cc,pcr
You can easily make your program twice as fast as follows:
org
$4000
start ldx
#$400
ldd
#$8080
loop std
,x++
cmpx
#$600
bne
loop
rts
end
start
The final end start will cause
EDTASM to place the correct start address in the header for the file
so that you just need to LOADM"SCREEN":EXEC
without the &Haddress.
MORE FROM ROBERT GAULT:
Subject: More on the clear screen routine <overkill :)
>
From: Robert Gault <email address removed to foil spam-bots>
Date: Mon, Apr 09, 2007 5:30 am
To: Robert <[email protected]>
Robert,
Here are more examples (maybe overkill) to show how you can evaluate
whether an "enhancement" is worth the trouble. The factors to consider
are size and speed of code.
The code will work with either EDTASM+ or Roger's Rainbow-IDE. You will
need another name for S_HOLDER with EDTASM+.
===============================================================
* This routine is the baseline algorithm.
* Clear low resolution text screen
ORG
$4000
START LDX
#$400
LDA
#$80
ORCC
#$50 turns off interrupts so counts are accurate
LOOP STA
,X+ 6 cycles
CMPX
#$600 4 cycles
BNE
LOOP 3 cycles
ANDCC
#$AF turn on interrupts
RTS
END
START
* 13 Cycles per loop; 1 loop clears 1 byte; $200 bytes per screen
* Screen = 13 * $200 = 6656 cycles at 0.89 MHz = 0.0075 seconds
* This routine is an obvious improvement on the basic algorithm.
* Clear low resolution text screen
ORG
$4000
START LDX
#$400
LDD
#$8080
ORCC
#$50 turns off interrupts so
counts are accurate
LOOP STD
,X++ 8 cycles
CMPX
#$600 4 cycles
BNE
LOOP 3 cycles
ANDCC
#$AF turn on interrupts
RTS
END
START
* 15 Cycles per loop; 1 loop clears 2 bytes; $200 bytes per screen
* Screen = 15 * $200 / 2 = 3840 cycles at 0.89 MHz = 0.0043 seconds
* This routine takes the technique a few steps further.
ORG
$4000
START LDX
#$400
LDD
#$8080
ORCC
#$50 turns off interrupts so
counts are accurate
LOOP STD
,X++ 8 cycles
STD
,X++ 8 cycles
STD
,X++ 8 cycles
STD
,X++ 8 cycles
CMPX
#$600 4 cycles
BNE
LOOP 3 cycles
ANDCC
#$AF turn on interrupts
RTS
END
START
* Here we take advantage of $200 being an even multiple of 8 bytes.
* 39 Cycles per loop; 1 loop clears 8 bytes; $200 bytes per screen
* Screen = 39 * $200 / 8 = 2496 cycles at 0.89 MHz = 0.0028 seconds
* This routine changes the algorithm for a significant boost in
speed.
ORG
$4000
START STS
S_HOLDER
LDS
#$600 the 6809 pushes down
LDD
#$8080
LDX
#$8080
LDY
#$8080
LDU
#$8080
ORCC
#$50 turns off interrupts so
counts are accurate
LOOP PSHS
D,X,Y,U 13 cycles
CMPS
#$400 5 cycles
BNE
LOOP 3 cycles
LDS
S_HOLDER
ANDCC
#$AF turn on interrupts
RTS
S_HOLDER RMB 2
END
START
* Here again we take advantage of $200 being an even multiple of
8 bytes.
* 21 Cycles per loop; 1 loop clears 8 bytes; $200 bytes per screen
* Screen = 21 * $200 / 8 = 1344 cycles at 0.89 MHz = 0.0015 seconds
* It is clear that the push routine is faster 1344 cycles vs 2496,
3840,
or 6656
* but as even the slowest routine takes much less than a second,
speed
is a moot
* point for this purpose.
*
* However if the Coco3 high res graphic screen is being cleared
which
might be
* $1E000 bytes, then the times would be 0.36 seconds vs 1.8 seconds.
I appreciate Robert Gaults input. I was hoping other's
would get involved, point out my mistakes and such. I have acually admired
his work for some time. In 1993 or 1994, right before CoCoPRO! went out
of business, I purchased a product called EDTASM6309 from them. This is
without a doubt the BEST assembler that I ever owned. Sadly, it went missing
with the rest of my original CoCo stuff years ago. However, Robert still
sells this product from his website for $35, and it is worth it! The Rainbow
IDE has similar functionality, I am told, but if you are working with a
REAL CoCo 3 instead of emulating, then I highly recommend this product.
Note that you do have to own a copy of Disk EDTASM+ in order to generate
the functioning version of EDTASM6309. YOU
CAN PURCHASE IT HERE.
STUDY ROBERT GAULTS EXAMPLES ABOVE - THERE
IS A LOT TO BE LEARNED FROM THEM.
page1.html
|