I think I've only understood half of what has been talked about in this thread, but I still know twice as much as I did before!
qalle wrote:
Most assemblers make no distinction between what the programmer calls "variables", "labels" or "constants". They are all just constants - they have a name and a value. (Edit: they have different syntax but I think they're internally the same.)
Yeah, the sticking point for me is that the number of bytes used for a variable changes how you work with the variable, (and maybe how you interpret the value if it is signed), but constants don't have a "size" that you can determine apart from their value. This is compounded by the fact that I'm both new to the language and also the capabilities of ca65.
I tried two approaches that I thought would work, but resulted in an error. Then I tried another approach that I assumed would give me an error but actually worked.
This yielded the error "Error: Constant expression expected"
Code: Select all
tempw0: .res 2
CONSTANT_1 = 1
.macro u16_set_from_constant setvar, constant
.if (constant >= 0 && constant <= 255)
lda #<constant
sta setvar+0
lda #$00
sta setvar+1
.elseif (constant >= 255 && constant <= 65535)
lda #<constant
sta setvar+0
lda #>constant
sta setvar+1
.else
.error "constant is out of range"
.endif
.endmacro
; macro called from some unit test subroutine
u16_set_from_constant tempw0, CONSTANT_1
This approach gave the error "Error: Size of `CONSTANT_1' is unknown"
Code: Select all
tempw0: .res 2
CONSTANT_1 = 1
.macro u16_set_from_constant setvar, constant
.if (.sizeof(constant) == 1)
lda #<constant
sta setvar+0
lda #$00
sta setvar+1
.elseif (.sizeof(constant) == 2)
lda #<constant
sta setvar+0
lda #>constant
sta setvar+1
.else
.error "constant is out of range"
.endif
.endmacro
; macro called from some unit test subroutine
u16_set_from_constant tempw0, CONSTANT_1
This one worked fine, somewhat to my surprise. I expected using ">" with a constant that wouldn't logically be a 2 byte value to result in a compile time error or some garbage values at runtime, but it works.
Code: Select all
.macro u16_set_from_constant setvar, constant
lda #<constant
sta setvar+0
lda #>constant
sta setvar+1
.endmacro
So I guess in this case ca65 knows that there is no "value" in the "high byte" and generates a value of $00 for the immediate mode operation. Maybe that should have been obvious to me, but I thought I was telling it to do something dumb and expected it to just let me shoot myself in the foot. But it works!