NESASM forces absolute addressing in zero page
Moderator: Moderators
NESASM forces absolute addressing in zero page
Hello all, this might come across as a noobish question and I apologize if it's been asked before (or I am missing something obvious), but I've noticed that nesasm always uses absolute addressing, even if I want to address the zero page. This happens regardless of whether I use labels or addresses, so both lda $00 and lda label (with label being a variable at $00) result in an AD 00 00 opcode. Also, sty $00, x results in an assembler error, as nesasm interprets $00 as an absolute address.
Now, my question is whether I can do something against it (other than manually writing every line as .db $A5, $00, for lda,zp), or whether it's about time I switched assemblers.
Cheers, -scrimpeh
Now, my question is whether I can do something against it (other than manually writing every line as .db $A5, $00, for lda,zp), or whether it's about time I switched assemblers.
Cheers, -scrimpeh
Re: NESASM forces absolute addressing in zero page
This is a known difference in syntax between NESASM and other popular 6502 assemblers. To switch to zero page, use explicit zero page addressing: lda <$FF or lda <some_var.
Re: NESASM forces absolute addressing in zero page
NESASM requires < before a zero page variable due to the fact that it's derived from a PC Engine/TurboGrafx 16 assembler (on that system, Zero Page is in the $2000 area).
My suggestions for alternative assemblers include asm6 (simpler) and ca65 (more complex).
My suggestions for alternative assemblers include asm6 (simpler) and ca65 (more complex).
Re: NESASM forces absolute addressing in zero page
tepples wrote:This is a known difference in syntax between NESASM and other popular 6502 assemblers. To switch to zero page, use explicit zero page addressing: lda <$FF or lda <some_var.
Oh wow, this is really simple. Thanks for the quick answers, too!freem wrote:NESASM requires < before a zero page variable due to the fact that it's derived from a PC Engine/TurboGrafx 16 assembler (on that system, Zero Page is in the $2000 area).
My suggestions for alternative assemblers include asm6 (simpler) and ca65 (more complex).
Re: NESASM forces absolute addressing in zero page
ASM6 on the other hand never uses absolute addressing for $0000-$00FF. If you happen to need that for timing reasons or something, you'll either have to use .db (for the opcode) and .dw (for the address) or a mirror of ZP ($0800-$08FF, for example).freem wrote:asm6 (simpler)
Re: NESASM forces absolute addressing in zero page
good to know, I thought it would do that if you just put $00xx. (guess that's something I should look into for my fork)tokumaru wrote:ASM6 on the other hand never uses absolute addressing for $0000-$00FF.freem wrote:asm6 (simpler)
Re: NESASM forces absolute addressing in zero page
Yeah, that's the one annoying ASM6 flaw that affects me in any significant way. It's still my assembler of choice, though.
I don't think I ever needed absolute addressing for $0000-$00FF on the NES, but it happens quite often when I'm programming kernels for Atari 2600 games.
I don't think I ever needed absolute addressing for $0000-$00FF on the NES, but it happens quite often when I'm programming kernels for Atari 2600 games.
Re: NESASM forces absolute addressing in zero page
What's the preferred way of handling it?
Assembler directive? (.zopt on/off)
Per instruction? (lda.w $ff, lda >$ff, lda $00ff ...?)
Assembler directive? (.zopt on/off)
Per instruction? (lda.w $ff, lda >$ff, lda $00ff ...?)
Re: NESASM forces absolute addressing in zero page
My preferences are unprefixed $00ff (which might not be simple/easy to handle; it's been a bit since I've looked at the code) or an a:$00ff prefix like ca65 supports. The former would be my preferred solution in a perfect world, and the latter would be my preferred solution in the real world
Re: NESASM forces absolute addressing in zero page
It does make the parsing more tricky, I'd have to add some special cases. 15 = %1111 = $f = $00000f, they all just evaluate to a number. What happens if you want to throw in arithmetic or labels?
Last edited by loopy on Fri Oct 31, 2014 4:46 pm, edited 1 time in total.
Re: NESASM forces absolute addressing in zero page
Matter of opinion, but this is my take on it, with some actual historical assembler reference documentation to back it up:
lda $00 through lda $ff (more specifically: a 2-digit address, or an address that's less than 256 in value (in case some crazy decided to do lda 257)) should get assembled as the zero page version. Addresses $100 or larger should get assembled as 16-bit addresses. For equates or mathematical operations, the equates or math should get expanded first (which has to be done anyways since they're assemble-time and not run-time generated) and the decision based off the calculated result. If someone wants to force the 16-bit equivalent, then they should be able to do either a) lda $0000 to lda $00ff, or, b) lda >$00 to lda >$ff (use of > modifier). If you support things like .w pseudo-ops then that should also force 16-bit equivalents (e.g. lda.w $ff would assemble to the 16-bit address).
Justification for this stems from the model/methodology implemented by the Apple IIGS ORCA/M assembler. Here's the manual. The relevant section that describes the above is on PDF pages 335/336 (actual document pages 309/310).
Likewise, the Apple II Merlin 8/16 assembler uses the same model but with a different syntax/modifier/methodology (and fairly risky/scary -- it's accomplished by adding any character to the end of the operand, other than "D" or "L", i.e. LDAq $ff would use 16-bit addressing, as would LDA- $ff or LDAq $ff. I believe they did this to be compatible with other assemblers). Here's that manual. The relevant section is PDF page 97 (document page 85).
lda $00 through lda $ff (more specifically: a 2-digit address, or an address that's less than 256 in value (in case some crazy decided to do lda 257)) should get assembled as the zero page version. Addresses $100 or larger should get assembled as 16-bit addresses. For equates or mathematical operations, the equates or math should get expanded first (which has to be done anyways since they're assemble-time and not run-time generated) and the decision based off the calculated result. If someone wants to force the 16-bit equivalent, then they should be able to do either a) lda $0000 to lda $00ff, or, b) lda >$00 to lda >$ff (use of > modifier). If you support things like .w pseudo-ops then that should also force 16-bit equivalents (e.g. lda.w $ff would assemble to the 16-bit address).
Justification for this stems from the model/methodology implemented by the Apple IIGS ORCA/M assembler. Here's the manual. The relevant section that describes the above is on PDF pages 335/336 (actual document pages 309/310).
Likewise, the Apple II Merlin 8/16 assembler uses the same model but with a different syntax/modifier/methodology (and fairly risky/scary -- it's accomplished by adding any character to the end of the operand, other than "D" or "L", i.e. LDAq $ff would use 16-bit addressing, as would LDA- $ff or LDAq $ff. I believe they did this to be compatible with other assemblers). Here's that manual. The relevant section is PDF page 97 (document page 85).
Re: NESASM forces absolute addressing in zero page
If you happen to need that for timing reasons or something on the 2600, you'll either have to use .db (for the opcode) and .dw (for the address) or a mirror of ZP ($0100-$01FF, for example).tokumaru wrote:I don't think I ever needed absolute addressing for $0000-$00FF on the NES, but it happens quite often when I'm programming kernels for Atari 2600 games.
Unless the address is a label defined later or imported from another file. For the latter situation, ca65 has .globalzp vs. .global.koitsu wrote:lda $00 through lda $ff (more specifically: a 2-digit address, or an address that's less than 256 in value (in case some crazy decided to do lda 257)) should get assembled as the zero page version. Addresses $100 or larger should get assembled as 16-bit addresses.
$0000 to $00FF expands to $0 to $FF. I'd recommend things like a: modifiers on an address expression to force its size.For equates or mathematical operations, the equates or math should get expanded first (which has to be done anyways since they're assemble-time and not run-time generated) and the decision based off the calculated result. If someone wants to force the 16-bit equivalent, then they should be able to do either a) lda $0000 to lda $00ff
Where I come from, >x means (x & $FF00) >> 8, the "high" byte of a value.lda >$00 to lda >$ff (use of > modifier).
Re: NESASM forces absolute addressing in zero page
We're not supposed to used hardcoded addresses in instructions, so the solution has to be something that works well for variables and expressions too.
being able to turn ZP addressing on and off is nice if for some reason you want this to affect several instructions, but you really need per instruction control in order to write timed code efficiently.
Personally I'd go for the operator suffix (.w), because it doesn't mess with the operand. When I'm coding for the Atari 2600, I may need to write to the same address but using different addressing modes each time depending on how many cycles I want. If the solution was something about how many 0's the address has, would I have to define the same variable twice? Once as $07 and again as $0007, giving them different names? should I add $0000 to it to force absolute addressing? none of that makes any sense. Modifying the operator is much cleaner.
being able to turn ZP addressing on and off is nice if for some reason you want this to affect several instructions, but you really need per instruction control in order to write timed code efficiently.
Personally I'd go for the operator suffix (.w), because it doesn't mess with the operand. When I'm coding for the Atari 2600, I may need to write to the same address but using different addressing modes each time depending on how many cycles I want. If the solution was something about how many 0's the address has, would I have to define the same variable twice? Once as $07 and again as $0007, giving them different names? should I add $0000 to it to force absolute addressing? none of that makes any sense. Modifying the operator is much cleaner.
Re: NESASM forces absolute addressing in zero page
Exactly, which is why I suggested the same be done the NES, if necessary. So far I've been using +$100 after variable names in my Atari 2600 programs, but I don't really like this.tepples wrote:If you happen to need that for timing reasons or something on the 2600, you'll either have to use .db (for the opcode) and .dw (for the address) or a mirror of ZP ($0100-$01FF, for example).
- rainwarrior
- Posts: 8734
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: NESASM forces absolute addressing in zero page
I don't think it really requires a special case for the assembler. You can just do it as data:
If needed frequently, it can become a macro very easily.
Code: Select all
.byte $AD ; LDA absolute
.word foo