NESASM forces absolute addressing in zero page

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

User avatar
scrimpeh
Posts: 11
Joined: Tue Aug 02, 2011 3:11 am

NESASM forces absolute addressing in zero page

Post by scrimpeh »

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
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: NESASM forces absolute addressing in zero page

Post by tepples »

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.
User avatar
freem
Posts: 176
Joined: Mon Oct 01, 2012 3:47 pm
Location: freemland (NTSC-U)
Contact:

Re: NESASM forces absolute addressing in zero page

Post by freem »

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).
User avatar
scrimpeh
Posts: 11
Joined: Tue Aug 02, 2011 3:11 am

Re: NESASM forces absolute addressing in zero page

Post by scrimpeh »

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.
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).
Oh wow, this is really simple. Thanks for the quick answers, too!
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: NESASM forces absolute addressing in zero page

Post by tokumaru »

freem wrote:asm6 (simpler)
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).
User avatar
freem
Posts: 176
Joined: Mon Oct 01, 2012 3:47 pm
Location: freemland (NTSC-U)
Contact:

Re: NESASM forces absolute addressing in zero page

Post by freem »

tokumaru wrote:
freem wrote:asm6 (simpler)
ASM6 on the other hand never uses absolute addressing for $0000-$00FF.
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)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: NESASM forces absolute addressing in zero page

Post by tokumaru »

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.
User avatar
loopy
Posts: 405
Joined: Sun Sep 19, 2004 10:52 pm
Location: UT

Re: NESASM forces absolute addressing in zero page

Post by loopy »

What's the preferred way of handling it?

Assembler directive? (.zopt on/off)
Per instruction? (lda.w $ff, lda >$ff, lda $00ff ...?)
User avatar
freem
Posts: 176
Joined: Mon Oct 01, 2012 3:47 pm
Location: freemland (NTSC-U)
Contact:

Re: NESASM forces absolute addressing in zero page

Post by freem »

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 :)
User avatar
loopy
Posts: 405
Joined: Sun Sep 19, 2004 10:52 pm
Location: UT

Re: NESASM forces absolute addressing in zero page

Post by loopy »

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.
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: NESASM forces absolute addressing in zero page

Post by koitsu »

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).
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: NESASM forces absolute addressing in zero page

Post by tepples »

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.
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).
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.
Unless the address is a label defined later or imported from another file. For the latter situation, ca65 has .globalzp vs. .global.
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
$0000 to $00FF expands to $0 to $FF. I'd recommend things like a: modifiers on an address expression to force its size.
lda >$00 to lda >$ff (use of > modifier).
Where I come from, >x means (x & $FF00) >> 8, the "high" byte of a value.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: NESASM forces absolute addressing in zero page

Post by tokumaru »

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.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: NESASM forces absolute addressing in zero page

Post by tokumaru »

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).
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.
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: NESASM forces absolute addressing in zero page

Post by rainwarrior »

I don't think it really requires a special case for the assembler. You can just do it as data:

Code: Select all

.byte $AD ; LDA absolute
.word foo
If needed frequently, it can become a macro very easily.
Post Reply