4
votes

My question is about the 6502 Assembly language. I'm trying to learn it using this website https://skilldrick.github.io/easy6502/.

On the topic of addressing modes. I don't understand the indirect addressing mode. See the source code example below.

LDA #$01
STA $f0
LDA #$cc
STA $f1
JMP ($00f0) ;dereferences to $cc01

Why is the JMP ($00f0) dereferenced to $cc01 instead of $01cc.

My memory looks like this

00f0: 01 cc 00 00 00 00 00 00 00 00 00 00 00 00 84

Here you see 00f0 starts with 01 and then followed by cc so it looks more logical to me that the jump instruction would dereference to $01cc, but why is this somehow reversed?

2
There are 01 kinds of people. Those who understand endianness ...Nick Westgate

2 Answers

6
votes

6502 is little endian. That means for 16 bit values, which take two bytes, the lowest byte is stored at the lowest address. After the two STAs, you have:

00f0: 01 
00f1: cc

The JMP instruction loads the byte at f0 into the low byte of the destination address and the byte at f1 into the high byte of the destination address meaning you jump to cc01.

4
votes

An additional answer on "why is this somehow reversed?": little endian obeys the direction in which carry runs, so is cheaper to implement. You have enough information to start doing arithmetic before you have all the information.

This is the cycle breakdown of 6502 when dealing with an $aabb, X instruction:

  1. fetch instruction
  2. fetch low byte of operand address
  3. add low byte of operand address to X register, fetch high byte of operand address
  4. read from address with high byte $aa and low byte $bb + X, if there was carry then work out $aa+1 for use in a moment...
  5. if there was carry then read from proper address

So if that's LDA then the cost is four cycles if you don't cross a page boundary, five if you do. Now imagine addresses were stored in big endian format. Then:

  1. fetch instruction
  2. fetch high byte of operand address
  3. fetch low byte of operand address
  4. add X to low byte of operand address
  5. read from address with high byte $aa and low byte $bb + X, if there was carry then work out $aa+1 for use in a moment...
  6. if there was carry then read from proper address

So you've increased cost by a cycle. You can't start until you have the low byte, and you're getting the low byte a cycle later.

So if you do not arrange things so that the lowest byte is fetched first then you are losing time.