Page 1 of 1 [ 2 posts ] 

MrOddBall
Velociraptor
Velociraptor

User avatar

Joined: 3 Feb 2014
Age: 126
Gender: Male
Posts: 426
Location: Here, there, and everywhere

10 May 2014, 6:06 pm

I was just wondering if I'm right about seeing the hex numbers for certain assembly op-codes and their operands in a retro NES Rom file when I'm viewing it in a hex editor ? If I'm right and it is op-codes and data that I'm seeing, then there'll also be addresses in there too, right ? I know there's addressing modes in 6502 that allows you to manipulate data and addresses as well ...

Is this correct ? This would help me a long way as I was confused and wasn't really sure, also I guess I could disassemble a NES Rom manually or write one in C or even Python ...



MrOddBall
Velociraptor
Velociraptor

User avatar

Joined: 3 Feb 2014
Age: 126
Gender: Male
Posts: 426
Location: Here, there, and everywhere

10 May 2014, 6:12 pm

For example, if I was to open a NES Rom in a hex editor and there's the hexes A9 05 8D 00 00 04, wouldn't that be the instructions LDA (Absolute) #$05 STA $0004 ?



beneficii
Veteran
Veteran

User avatar

Joined: 10 May 2005
Age: 42
Gender: Female
Posts: 7,245

10 May 2014, 6:49 pm

This zip file has both a txt and doc file that give a list of opcode conversions for the instructions and their addressing modes--I prefer the txt file:

http://nesdev.com/6502jsm.zip

It's from nesdev.com

Looking at your example, are you sure you copied the machine code correctly?

From A9 05 8D 00 00 04 you would get:

LDA #$05 ; absolute addressing, yes, and you got this right
STA $0000 ; you got this wrong; now you are correct that this is accesses the value at the 16-bit address (in this case $0000), but 04 comes after the end of the instruction
; 04 is not a valid op code so if the program came up on this 04, there would be an unpredictable effect (a crash most likely)

Now, I'm guessing you only intended to put 1 00 in there, so it would be A9 05 8D 00 04, which would dissassemble to:

LDA #$05
STA $0400

(EDIT 3: This bit of code loads the value $05 into the accumulator and then stores the accumulator's value (which now is $05 thanks to the previous instruction) at the 16-bit address $0400.)

Remember that 6502 machine code is always little-endian, which means that for 16-bit values, the least significant byte comes first. So 00 04 combines to $0400 (00 is least significant and 04 is most significant), while 04 00 combines to $0004.

Source: Me. I have considerable experience doing ASM hacking of NES/FDS ROMS, to include manual assembly and disassembly and even have worked on my own disassembly of a game, this one of SMB2j:

http://sm2.beneficii.net/

EDIT: I also created the SMB3 Map Editor and the ASM hack of the start spaces that accompanies the editor as an IPS patch.

EDIT 2: Corrected my own opcode, do'h! ;)


_________________
"You have a responsibility to consider all sides of a problem and a responsibility to make a judgment and a responsibility to care for all involved." --Ian Danskin


MrOddBall
Velociraptor
Velociraptor

User avatar

Joined: 3 Feb 2014
Age: 126
Gender: Male
Posts: 426
Location: Here, there, and everywhere

10 May 2014, 11:08 pm

beneficii wrote:
This zip file has both a txt and doc file that give a list of opcode conversions for the instructions and their addressing modes--I prefer the txt file:

http://nesdev.com/6502jsm.zip

It's from nesdev.com



Thanks for the op-code list :D Have you ever been around nesdev.com as well as romhacking.net and Zolphar's domain ? :D Those sites have a lot of tools and documentation on a lot of consoles except maybe the newer ones like the PS3 XBox 360 or PS4 lol



Quote:
Looking at your example, are you sure you copied the machine code correctly?


Actually I just made that up as an example of what I was trying to explain :oops:


Quote:
From A9 05 8D 00 00 04 you would get:

LDA #$05 ; absolute addressing, yes, and you got this right
STA $0000 ; you got this wrong; now you are correct that this is accesses the value at the 16-bit address (in this case $0000), but 04 comes after the end of the instruction
; 04 is not a valid op code so if the program came up on this 04, there would be an unpredictable effect (a crash most likely)

Now, I'm guessing you only intended to put 1 00 in there, so it would be A9 05 8D 00 04, which would dissassemble to:

LDA #$05
STA $0400

(EDIT 3: This bit of code loads the value $05 into the accumulator and then stores the accumulator's value (which now is $05 thanks to the previous instruction) at the 16-bit address $0400.)


So too many 0's ?

Quote:
Remember that 6502 machine code is always little-endian, which means that for 16-bit values, the least significant byte comes first. So 00 04 combines to $0400 (00 is least significant and 04 is most significant), while 04 00 combines to $0004.


That's been a really hard thing for me to remember that the least significant byte comes first instead of the most significant byte :oops:

Quote:
Source: Me. I have considerable experience doing ASM hacking of NES/FDS ROMS, to include manual assembly and disassembly and even have worked on my own disassembly of a game, this one of SMB2j:

http://sm2.beneficii.net/

EDIT: I also created the SMB3 Map Editor and the ASM hack of the start spaces that accompanies the editor as an IPS patch.

EDIT 2: Corrected my own opcode, do'h! ;)


I've checked out your site and think it's pretty cool myself :D Thanks for ite :)



beneficii
Veteran
Veteran

User avatar

Joined: 10 May 2005
Age: 42
Gender: Female
Posts: 7,245

11 May 2014, 11:02 am

Yes, been around both. Zophar's Domain is an oldy, but still good for getting things like the soundtracks of video games in their original code form so you can play them over and over again.

Remember, when you use 16-bit addressing, the instruction will only be 3 bytes long:

byte 0: opcode
byte 1: least significant byte
byte 2: most significant byte

If using absolute, zero-page (8-bit addressing), or branch-on-condition (e.g. BCC, BEQ):

byte 0: opcode
byte 1: absolute value, zero-page address, or (for branching instructions) the distance from the first byte following this current byte we're talking about of the address to where you're supposed to branch if the condition tested by the branching instruction is true (this is a signed integer, so you can go backwards or forwards)*. Some examples are BCC, which means branch if carry (C) flag is cleared (otherwise, don't branch and simply move onto next instruction), and BEQ, which means branch if zero (Z) flag is set (otherwise, don't branch '').

And of course for all those op-codes that don't have an addressing mode at all:

byte 0: opcode

Again, no instruction takes up more than 3 bytes (and this includes the opcode itself).

*Signed integers are integers that can be either positive or negative. In 6502, signed integers, whether they are negative or not, are determined by the most significant bit (if the most significant bit is 1, then it's negative; if it's 0, then it's positive). Basically, it follows this pattern (for 8-bit signed integers):

+5 = $05 = %00000005
+4 = $04 = %00000004
+3 = $03 = %00000003
+2 = $02 = %00000002
+1 = $01 = %00000001
0 = $00 = %00000000
-1 = $FF = %11111111
-2 = $FE = %11111110
-3 = $FD = %11111101
-4 = $FC = %11111100
-5 = $FB = %11111011

(Notice the most significant bit, which is the leftmost bit when written in binary, is set to 1 for negative numbers.)

For 16-bit signed integers, which are not used for anything in the instructions, but which may be useful still in programming, go like this:

+5 = $0005
+4 = $0004
+3 = $0003
+2 = $0002
+1 = $0001
0 = $0000
-1 = $FFFF
-2 = $FFFE
-3 = $FFFD
-4 = $FFFC
-5 = $FFFB

(Basically, to get the correct way of storing negative values, you need to know the width (e.g. 8-bit, 16-bit) of the integer.)

This is known as the two's complement way of representing signed integers, and is the way you should use when programming with 6502, as it is best designed for that. More on signed integers here, as well as the overflow (V) flag which is relevant to addition and subtraction of signed integers (as, to be honest, even I don't fully understand it):

http://www.6502.org/tutorials/vflag.html

EDIT: Corrections and adjustments


_________________
"You have a responsibility to consider all sides of a problem and a responsibility to make a judgment and a responsibility to care for all involved." --Ian Danskin