See also: part 1, part 2, part 3, part 4, part 5 and part 6.
Previously, we took a look at using the EXTENDED COLOR BASIC DEFUSR command to interface a bit of assembly language with a BASIC program. The example I gave simply added one to a value passed in:
That’s not very useful, so let’s do something a bit more visual.
One of my favorite bits of CoCo 6809 assembly code is this:
org $3f00 start ldx #$400 * load X with start of 32-column screen loop inc ,x+ * increment whatever is at X, then increment X cmpx #$600 * compare X with end of screen bne loop * if not end, go back to loop bra start * go back to start
This endless loop will start incrementing every byte on the screen over and over making a fun display. I ran this code in the Mocha emulator (which has EDTASM available):
Then I compiled it (“A/IM/WE/AO” – assemble, in memory, wait for errors, absolute origin – how can I still remember this???), and ran it in the debugger (“Z” for debugger, then “G START” to start it):
This inspired me to make a small assembly routine to do something similar from BASIC. The CLS command can take an optional value (0-8) to specify what color to clear the screen to. Let’s make an assembly routine that will allow specifying ANY character to clear the screen to:
ORGADDR EQU $3f00 GIVABF EQU $B4F4 * 46324 INTCNV EQU $B3ED * 46061 org ORGADDR start jsr INTCNV * get passed in value in D cmpd #255 * compare passed in value to 255 bgt error * if greater, error ldx #$400 * load X with start of screen loop stb ,x+ * store B register at X and increment X cmpx #$600 * compare X to end of screen bne loop * if not there, keep looping bra return * done error ldd #-1 * load D with -1 for error code return jmp GIVABF * return to caller
First, I added a bit of error checking so if the user passed in anything greater than 255, it will return -1 as an error code. Otherwise, it returns back the value passed in (that the screen was cleared to.)
Side Note: Hmmm. Since I know register D is register A and B combined, all I really need to do is make sure A is 0. i.e, “D=00xx”. If anything is in A, it is greater than the one byte value in B. I suppose I could also have done “cmpa #0 / bne error”. Doing something like that might be smaller and/or faster than comparing a 16-bit register. Anyone want to provide me a better way?
Since the 16-bit register D is made up of the two 8-bit registers A and B, I can just use B as the value passed in (0-255).
Here is what it would do with a bad value:
And here is it with a valid value of 42:
So far so good.
In the next part, we’ll look at how to pass in a string instead of an integer.
You could also just do a clra to force the issue and avoid the compare and branch.
Well, if not testing, those two instructions could be removed, but then if you only look at B, if they passed in 256, it would look like zero. Is it better to proceed with bad data and give unexpected results, or ignore bad data?
You could use TSTA. instead of CMPA #$00 to save a byte.
Cool. I forgot about TST. Thanks!