Table of Contents
ASM
PET VIC-20 C64 C16 Plus/4 C128 X16 M65
Syntax
ASM <assembly code> <assembly code> END ASM
The ASM
directive injects bare 6502 assembly code into the compiled XC=BASIC code without any modification. As XC=BASIC itself produces dasm code, the injected assembly code must also be in dasm format and syntax.
Example
REM -- set border to black using XC=BASIC code POKE $d020, 0 REM -- set background to black using inline assembly ASM lda #$00 sta $d021 END ASM REM -- the XC=BASIC program continues on from here PRINT "done" END
The above example illustrates how to use ASM
to inject inline assembly code into the XC=BASIC program. The compiler will send the code between the ASM … END ASM
commands straight to dasm for assembly immediately following the POKE command. Newlines are used in this example to improve the readability of 6502 assembly code that spans beyond one line. Note there are no quotation marks or other encapsulations around the assembly code as was previously required in XC=BASIC v2.
Note the spaces before the opcodes on each line of dasm assembly code. Leading spaces are required by dasm for any line of assembly that is not a valid label in dasm.
Warning
Each line in dasm assembly code must start with a label or at least one space.
Note
The XC=BASIC compiler cannot validate the in-line assembly code. It will be copied verbatim into the XC=BASIC assembly before being compiled by dasm, so you must take special care with the ASM
directive. Dasm will report any errors. Please consult the dasm docs carefully for syntax and formatting.
Referencing BASIC Non-String Variables in Assembly Code
To use BASIC non-string variables in assembly code, use the syntax {variable_name}
. For example:
a = 2 : REM global variable b = 7 SUB test () STATIC DIM a AS BYTE : REM local variable a = 5 ASM lda #$06 sta {a} ; {a} is resolved to the local "a" sta {b} END ASM PRINT a END SUB CALL test () PRINT a PRINT b
Warning
Only STATIC variables can be referenced using the curly braces syntax.
Referencing Strings in Assembly Code
Passing an XC=BASIC string by reference will not always produce expected results, because XC=BASIC strings in memory are preceded by a single byte string length and are not zero-terminated. Therefore, strings for operations like KERNAL calls (SETNAM, for example) must be be converted first. There are a couple of techniques you can use to accomplish this:
- Place the string into unused memory and terminate it with a zero byte, then reference that location in the assembly code
- Create a byte array with stringlen + 1 elements, convert the string to a KERNAL-friendly format, then pass the array by reference in the assembly code
An example of the byte array technique:
' create a byte array, fill it with the string "file," and zero-terminate it DIM fname(5) AS BYTE fname(0) = ASC("f") fname(1) = ASC("i") fname(2) = ASC("l") fname(3) = ASC("e") fname(4) = 0 ' set KERNAL SETNAM routine to point to fname ASM lda #$01 ldx #<{fname} ; set lo byte to fname lo ldy #>{fname} ; set hi byte to fname hi jsr $ffbd ; SETNAM Kernal routine END ASM
Or, if you have a longer string that you want to pass, consider iterating over the string with MID$
(see the following example) to simplify the conversion of a string into a byte array. Note that XC=BASIC will reset the string variable's length to the actual length of the assigned string every time a string is assigned to that variable, so you don't need to worry about calculating the length using some other trick if you've assigned a string shorter than the full dimension of the variable. LEN(string)
will work:
DIM a(22) AS BYTE DIM x AS BYTE DIM b AS STRING * 20 b = "the quick brown fox" ' will result in a byte array of "the quick brown fox" ' and a zero byte in the next array element, ready ' for use by a KERNAL call FOR x = 0 to LEN(b) a(x) = ASC(MID$(b, x, 1)) NEXT a(len(b) + 1) = 0