The Noob's Machine Code Thread
Posted: Thu Apr 14, 2022 11:15 pm
I may have been away a while, but I am not dead. And over the last three days, I've been hammering away on a QL again. (Well, QemuLator, but you get the idea). And I have written a fine SuperBASIC program - which works exactly the way I want it to, except for a few sound effects that I haven't experimented with yet - and I could release it as it is.
BUT - the original version of this program was a vehicle to show that I could use machine code on the ZX81, and because I had no access to an assembler, I had to assemble it by hand, and therefore keep it simple. And hence, the QL port of this program will be much the same - it will showcase my first determined attempt at 68008 machine code.
I have already found Andrew Pennell's book on the subject and it explains the instructions in a way I can understand, as well as introducing a few more that I might find useful, and already I'm translating the various MOVEs into their LD equivalents so I can understand it better. If it has a Z80 equivalent - and bear in mind I'm never going to go near the interrupt or stack pointer instructions until Death Valley freezes over - the chances are I won't have too many troubles with it.
I'm also looking at this Computer One assembler, or at least its manual, to see if it might serve my purpose, because hand-assembly looks very complicated.
But before I do anything, I just need to check that I've got the idea of RESPR right, and to check that I can do what I'm about to describe. If I start with mcs=RESPR(1024), I get a kilobyte of space somewhere in the QL's memory, for which the variable mcs stores the value of the first byte. Most people would start their programs at that first byte... but not me. I need the first six bytes to be available to POKE values four values in from BASIC, perform machine code manipulations on them, and dump the results in the other two bytes which can be PEEKed and used in the rest of the program. It's effectively a function to take two strings of length 2 and combine them into one by some Amazing Secret Formula (which is the machine code).
Is there a "correct" way to achieve this? My default method would be to use three NOPs (two bytes each) and it doesn't matter if that bit of code gets erased, it didn't do anything anyway, the important thing is that the space is there.
So if I've got this right, this should be the correct approach...
I can already see one thing I might have trouble with - the not-entirely-obvious 68008 equivalents of PUSH and POP. All I can gather is that it'll involve register A7 in some way. Fortunatelty, the Z80 code I'm trying to convert doesn't use the stack at all, so this can wait for another day.
BUT - the original version of this program was a vehicle to show that I could use machine code on the ZX81, and because I had no access to an assembler, I had to assemble it by hand, and therefore keep it simple. And hence, the QL port of this program will be much the same - it will showcase my first determined attempt at 68008 machine code.
I have already found Andrew Pennell's book on the subject and it explains the instructions in a way I can understand, as well as introducing a few more that I might find useful, and already I'm translating the various MOVEs into their LD equivalents so I can understand it better. If it has a Z80 equivalent - and bear in mind I'm never going to go near the interrupt or stack pointer instructions until Death Valley freezes over - the chances are I won't have too many troubles with it.
I'm also looking at this Computer One assembler, or at least its manual, to see if it might serve my purpose, because hand-assembly looks very complicated.
But before I do anything, I just need to check that I've got the idea of RESPR right, and to check that I can do what I'm about to describe. If I start with mcs=RESPR(1024), I get a kilobyte of space somewhere in the QL's memory, for which the variable mcs stores the value of the first byte. Most people would start their programs at that first byte... but not me. I need the first six bytes to be available to POKE values four values in from BASIC, perform machine code manipulations on them, and dump the results in the other two bytes which can be PEEKed and used in the rest of the program. It's effectively a function to take two strings of length 2 and combine them into one by some Amazing Secret Formula (which is the machine code).
Is there a "correct" way to achieve this? My default method would be to use three NOPs (two bytes each) and it doesn't matter if that bit of code gets erased, it didn't do anything anyway, the important thing is that the space is there.
So if I've got this right, this should be the correct approach...
Code: Select all
100 mcs=RESPR(1024)
110 LBYTES ...(load in the code from outside)
...
1000 POKE mcs,CODE(a$(1))
1010 POKE mcs+1,CODE(a$(2))
1020 POKE mcs+2,CODE(b$(1))
1030 POKE mcs+3,CODE(b$(2))
1040 CALL mcs+6
1050 c$=CHR$(PEEK(mcs+4))&CHR$(PEEK(mcs+5))
I can already see one thing I might have trouble with - the not-entirely-obvious 68008 equivalents of PUSH and POP. All I can gather is that it'll involve register A7 in some way. Fortunatelty, the Z80 code I'm trying to convert doesn't use the stack at all, so this can wait for another day.