I've noticed when disassembling some roms that when they do the wait for vblank they'll say BPL $FB. But what does the $FB stand for? Cause I've seen it used like so:
LDX #$12
LDA #$00
STA $00,X
INX
BNE $FB
Which is obviously supposed to be a loop. Can anyone explain this to me?
Thanks
$FB is a signed number, it's the relative address to branch to. In that example, -5 bytes.
Code:
LDX #$12
LDA #$00
loop:
STA $00,X
INX
BNE loop
Branches use relative addresses, not absolute addresses like JMP/JSR. The 1-byte operand is a signed value specifying the number of bytes to jump over. If greater than or equal to $80, the signed value is negative, so it jumps backwards the proper number of bytes.
$FF = -1
$FE = -2
$FD = -3
$FC = -4
$FB = -5
and so on
Remember it will branch;
-125/+129
not
-128/+127
as most sites will tell you.
ProgramCounter = ProgramCounter + Value + 2
Or more specifically;
Code:
(char)CPU.Memory[(unsigned short int)(CPU.PC + 1)] + 2
This happens when you disassemble stuff. The source code is, most of the time, well organized and everything is labeled. But when the code is assembled, all labels are lost and translated into adreeses, absolute or relative. This makes disassembling stuff a hard thing, and you'd most likely have to follow the program from the start to reconstruct all the labels. Actually, put them in place, because the names can never be restored.
It actually is -128/+127 ... but from the end of the instruction (after the branch opcode+operand). This is because the PC is auto-incremented after fetching both the opcode byte and operand byte.
But yeah... if you have the PC origin before the opcode (as opposed to after it), you'll have to add an additional 2 with the branch.
THanks a lot, that makes a lot of sense. I hadn't heard of relative branching before this but now I understand.
Just to round this out, the reason for having relative addressing in the fist place is that it results in more compact code, since most branches are to a nearby location, and it allows code to be relocated without having to update the addresses of branches (useful in an operating system, but not much in the NES).