Using inline assembly with CC65?

All aspects of programming on the Commander X16.
Post Reply
cosmicr
Posts: 36
Joined: Tue Nov 14, 2023 4:29 am

Using inline assembly with CC65?

Post by cosmicr »

I'm new to C, and 6502 coding in general.

I'm trying to mix in a bit of inline assembly but I keep getting the error:
Error: Constant integer expression expected

I read the CC65 manual on inline assembly, and they even use examples of close to what I'm doing but it's not working.

Code: Select all

    uint8_t lowByte = address & 0xFF;         // Low byte (7:0) of the start address
    uint8_t midByte = (address >> 8) & 0xFF;  // Middle byte (15:8) of the start address
    uint8_t highBit = (address >> 16) & 0x01; // High bit (16) of the start address

    // Set the starting address of VRAM
    __asm__("lda #%b", lowByte);
    __asm__("sta $9F20");
    __asm__("lda #%b", midByte);
    __asm__("sta $9F21");

    // Set the high bit of the address (17th bit) and set address increment
    __asm__("lda #%b", highBit | 0x10);
    __asm__("sta $9F22");
I am able to get it to work using global static variables:

Code: Select all

static uint8_t lowByte;  // Low byte (7:0) of the start address
static uint8_t midByte;  // Middle byte (15:8) of the start address
static uint8_t highBit;  // High bit (16) of the start address

// ... more code here

    lowByte = address & 0xFF;         // Low byte (7:0) of the start address
    midByte = (address >> 8) & 0xFF;  // Middle byte (15:8) of the start address
    highBit = (address >> 16) & 0x01; // High bit (16) of the start address

    // Set the starting address of VRAM
    __asm__("lda %v", lowByte);
    __asm__("sta $9F20");
    __asm__("lda %v", midByte);
    __asm__("sta $9F21");

    // Set the high bit of the address (17th bit) and set address increment
    __asm__("lda %v", highBit);
    __asm__("ora #$10");  // Combine with bit 4 set for auto-increment
    __asm__("sta $9F22");
but I am not happy with how this works because I prefer to keep everything encapsulated.

I can also get it working using either #defines or typing in the values directly.

What does "Error: Constant integer expression expected" mean?
DragWx
Posts: 345
Joined: Tue Mar 07, 2023 9:07 pm

Re: Using inline assembly with CC65?

Post by DragWx »

Don't worry, you just have a syntax error.

The opcode "LDA #n" means, "grab this hardcoded number of n".
The opcode "LDA n" (without the #) means, "interpret the value of n as a memory address, and go grab the number stored in that location."

Next, the tokens %b, %w, and %l are how you tell the inline assembler you want the C compiler to calculate a plain number to replace the token with. Since lowByte is a runtime variable, it cannot compile to a "plain number" the same way the expression "2 * 8 + 3" can. That's what the error means, that you're trying to use the "plain number" token but your input cannot be compiled down to a plain number.

Accessing global variables with the %v token is far-and-away the easiest way to share variables between C and ASM.

To use local variables, the best I can find, other than everyone just saying "use static variables instead", is that you do something like this:

Code: Select all

__asm__("ldy #%o", myVariable);
__asm__("lda (sp),y");
Where "sp" is a token the assembler understands (i.e., it's not part of 6502), and the %o token is specifically for doing this exact thing.

Basically, C allocates local variables on a stack. CC65 uses a software stack for this (referenced by the sp token), and %o gives you the stack offset for a local variable, specifically so you can use it in 6502 with opcodes that use the (nn),Y addressing mode.

Sorry, I know that was a lot of technical info to just dump in one post, so let me know if you'd like me to elaborate on anything. :P
cosmicr
Posts: 36
Joined: Tue Nov 14, 2023 4:29 am

Re: Using inline assembly with CC65?

Post by cosmicr »

Thanks! This makes a lot more sense. I'm slowly getting the hang of it. I'm writing my own plot_pixel function from scratch. I realise someone probably has already done this, but I'm trying to work it out for myself. I'll post results later :)
Post Reply