BASIC To Machine Language
I have a VIC and am currently learning machine language. How can I pass BASIC variables to an ML subroutine?
David P. Ballin
One of the easiest ways to transfer numbers between BASIC and machine language is to store them in memory. Safe memory locations can be used like post office boxes—BASIC can POKE the mail into the boxes, and machine language can pick it up, or vice versa. Here's an example:
300 A = 57 310 POKE 251, A 320 SYS 4096
In machine language:
$1000 CLC $1001 LDA $FB ;get the value POKEd into 251
Of course, this assumes that location 251 is unused for anything else. Now, here's the reverse (transferring data back to BASIC):
In machine language:
$1C49 STA $FB ;store the accumulator value into location 251($FB) $1C4B RTSIn BASIC:
500 A = PEEK(251)
With a single POKE you can transfer values in the range of 0 to 255 back and forth. If you want to transfer values larger than 255, use the following formula (where N is the number to be stored):
NN = INT (N/256) : POKE bytel, N — (NN * 256) : POKE byte2, NN
This method breaks the value of N into two bytes. The value in memory location byte 1 is the remainder after the integer division of N by 256. The quotient is placed in the following memory location, byte2. The bytes are stored low (least significant) byte first, then high (most significant) byte, a 6502 standard for two-byte numbers. Some good areas for temporary data storage on the VIC are locations 679–767, 828–1019 (the cassette buffer), and 251–254 (free zero page locations). The same locations are available on the Commodore 64, plus 4K of free RAM at 49152–53247.
You can also load the accumulator, X, and Y registers from BASIC on a VIC or 64 with the POKE statement. The accumulator is stored in 780 ($30C), the X register in 781 ($30D), the Y register in 782 ($30E), and the status register, P, in 783 ($30F).
Before a SYS statement in BASIC passes control to the SYS address, each register is loaded with the value found in the corresponding storage address. After the ML program finishes execution and returns to BASIC with the RTS instruction, the new value of each register is stored in the appropriate location. This is true only of SYS, not the USR function.
A useful application of this would be formatting the screen by using Kernal routines from BASIC. For instance:
POKE781,10 : POKE782,5 : POKE783,0 : SYS65520 : PRINT "HELLO"
This prints "HELLO" at row 10, column 5. This line will work on both the VIC and 64, as the PLOT routine is entered via the Kernal jump table.
Another, more tricky way to pass a single value back and forth between BASIC and ML is with the USR function. Like any function, it looks for a value in parentheses. This value is passed to the machine language program. And like any function, it returns a value. A = USR (B) would pass the value of B to the machine language program, which can then pass back a value to be stored into A.
For more information, see Mapping the VIC, Mapping the Commodore 64, or any of the machine language books from COMPUTE! Books.