It is currently Fri Oct 20, 2017 2:02 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: Nesasm(?) error
PostPosted: Thu Jul 03, 2008 11:50 am 
Offline

Joined: Tue Jul 01, 2008 9:53 pm
Posts: 6
My code is getting a little big, and it appeared today:

Code:
I:\NesProgramming\sprites>NESASM3 sprites.asm
NES Assembler (v3.00)

pass 1
pass 2
#[2]   Controller.asm
   14  00:C16C              BEQ ReadAllDone
       Branch address out of range!
# 1 error(s)

I:\NesProgramming\sprites>pause


What I do? :(

tks


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 03, 2008 12:04 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10063
Location: Rio de Janeiro - Brazil
Instead of branching to the location, branch around a JMP to the location. Say you have the following:
Code:
   bne FarAway
   (...)
FarAway:

Which doesn't assemble because "FarAway" is too far. Just do the following:
Code:
   beq DontJump
   jmp FarAway
DontJump:
   (...)
FarAway:

That's it. Use the branch to check for the inverse condition and skip the JMP instruction.

EDIT: Just to make it clear, it's not a NESASM error, it's a limitation of the 6502. Branches use relative addressing, which means that the displacement is calculated based on the difference between the current location and the destination location. It uses a byte to hold that difference, and if it's too large (the destination is too far away), it will not fit in just 8-bits, so the assembler throws an error. Jumps on the other hand use absolute addresses, so it's possible to jump anywere in the program (bankswitching aside). The solution is to combine both instructions, a branch and a jump.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 03, 2008 12:27 pm 
Offline

Joined: Tue Jul 01, 2008 9:53 pm
Posts: 6
Thank you, now it worked!! :D :D
Now I understand what happens, thank you for explaining. Sometimes we do things without knowing why we do .. tks :D


Top
 Profile  
 
 Post subject: Re: Nesasm(?) error
PostPosted: Mon Nov 21, 2016 6:12 am 
Offline

Joined: Tue Apr 11, 2006 4:08 am
Posts: 238
Is this method also works with other branches? As BEQ, BMI, BPL, etc.?
Or maybe there are some limitations and can not always be used?


Top
 Profile  
 
 Post subject: Re: Nesasm(?) error
PostPosted: Mon Nov 21, 2016 9:04 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10063
Location: Rio de Janeiro - Brazil
It works for any branch instruction, but you always have to use the opposite branch condition to skip over the JMP. Say you want to BCC somewhere, but the distance is to large, so instead you BCS over a JMP to the desired target location.


Top
 Profile  
 
 Post subject: Re: Nesasm(?) error
PostPosted: Mon Nov 21, 2016 4:50 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3192
Location: Mountain View, CA, USA
sdm wrote:
Is this method also works with other branches? As BEQ, BMI, BPL, etc.?
Or maybe there are some limitations and can not always be used?

The "method" isn't magical or mystical in some manner -- no CPU should be "magical". This is a computer, it has definitive behaviour. Your question implies that you don't understand branches (vs. jumps), so let's put that to rest:

Branch instructions on the 6502 are opcodes bpl, bmi, bvc, bvs, bcc (blt), bcs (bge), bne, beq. These instructions consist of 2 bytes: 1 byte for the opcode, and 1 byte for the operand. The operand being 1 byte in size is the key to understanding branches. The operand represents an "offset" from the active PC (the address of the operand, not the opcode!) -- this is also known as a "relative address" or "PC relative".

The operand is therefore a signed 8-bit number (more precisely: its twos complement), which means that the range it's limited to is +127 bytes (up to 127 bytes "forward", i.e. values $01 to $7F) and -128 (up to 128 bytes "backwards", i.e. value $80 to $FF) from the address of the operand. Thus, the branch range "from the branch opcode itself" is effectively +129 and -126. A little-mentioned quirk/feature is how an operand value of $00 on a branch instruction just continues on with the next instruction regardless of the conditional results (think of it as a 2-byte nop with a variable cycle count dependant on the result of the conditional).

The reason branch instructions are 2 bytes (rather than 3 (see below)) is to save space/memory.

In contrast, jump instructions on the 6502 are opcode jmp, jsr. This instruction consists of 3 bytes: 1 byte for the opcode, and 2 bytes for the location to jump to -- this is known as an "absolute address" (the same type of addressing used in something like sta $2100). The operand specifies a literal value from $0000 to $FFFF, which the CPU loads directly into PC. I won't explain the difference between jmp and jsr here -- it's not relevant to what is being discussed (relative vs. absolute addressing). And as should be obvious, jump instructions are unconditional.

The way people work around the relative addressing range on the 65xx is by doing exactly what tokumaru described -- the most common being to reverse the branch logic and use a jmp.

Edit: clarification on branches with an operand of $00.


Top
 Profile  
 
 Post subject: Re: Nesasm(?) error
PostPosted: Mon Nov 21, 2016 5:12 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10063
Location: Rio de Janeiro - Brazil
Koitsu is right, this is not some mystical voodoo stuff, it's just a very logical way to get around a limitation of the CPU. If you didn't yet understand why this works, please tell us what is confusing you so we can explain it better.

In a nutshell, you have to replace a branch, that has limited range, by a jump, that can reach the whole program. Problem is, a jump is unconditional, so in order to guarantee that it will only happen when a certain condition is met, you need to avoid the jump (i.e. branch over it) when the opposite condition is met.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group