Assembly Hacking
From Sonic Retro
It has been suggested that this page be moved over to Sega Retro as to be in accordance with both sites' policies. Please see the talk page for relevant discussion and export procedure. |
Assembly hacking, or ASM hacking, is the process of modifying a game's code instead of its data. This requires reverse engineering the relevant portion of the game.
Contents
Assembly languages
Knowing an assembly language doesn't help a whole lot if the language you know is the wrong one. On the other hand, it will certainly make things a whole lot easier than if you are completely unfamiliar with assembly. Each processor will have its own language, for instance, the 6502 is very different from the 68000 (and much harder to use).
The order of assembly languages you may come across from easiest to toughest to use are roughly:
- Motorola 68000 (Mega Drive)
- Zilog Z80 (Master System, Game Gear)
- 65c816 (SNES)
- 6502 (Atari, NES, PC Engine)
This is not necessarily the order in which they are easy to learn. For instance, the 6502 has far fewer instructions than the Z80. However, it has fewer registers, and they are smaller, so that it is more difficult to figure out the best way to do something -- something that may be perfectly straightforward on another processor, such as how to multiply two 16-bit numbers together. In general, the more powerful a processor is (in terms of functionality rather than speed), the easier it is to use but the harder it is to learn.
All assembly languages have a few things in common. For instance, each processor, and therefore its assembly language, has a few registers. A program carries out its tasks by manipulating these registers and memory. However, what registers are present and what they can do varies from processor to processor. For instance, the 6502 and Z80 both have a register named A which are similar in purpose, but are used in entirely different ways. All processors have a flags register, and they often have the same kind of flags, but the exact conditions which may set or clear a certain flag varies from processor to processor.
Basics of assembly language
Kinds of registers
Accumulator
All processors have at least one register that acts as an "accumulator". On the 6502 and Z80, it's named A; on the x86, it's AX; on the M68000, every D register acts as a sort of accumulator.
The accumulator is the primary register used for math.
Indexing registers
All processors have at least one indexing register. On the 6502, they're X and Y; on the Z80, the primary indexing registers are IX and IY. All A registers are indexing registers on the M68000.
Counting registers
Registers used for counting aren't uncommon. On the 6502, these are usually X and Y (same as the indexing registers).
Program counter
The program counter, or PC, is a register that holds the address of the current location in code. For example, if the PC is 8000, then the next instruction to execute is located at 8000.
Memory
Addresses
The stack
The stack is a region in memory that contains temporary storage. Sometimes the processor specifies where the stack goes; for instance, the 6502 specifies that the stack is from $0100 to $01FF.
To use the stack, you push data in a register on it, and later pop it back into a register (it doesn't have to be the same register). Suppose register A holds a value that you need to keep, but you need register A for something else right now. So you push A onto the stack. Let's say the stack has the bytes 00 01 02, and A holds 10. Then the stack becomes 00 01 02 10. When you pop the value back into A, A will hold 10 again, and the stack will again become 00 01 02. The stack pointer contains the address at the top of the stack, so in our example, when you push 10 onto the stack, the stack pointer contains the address of that byte.
It's important to note that calling a subroutine (such an instruction is usually named JSR, BSR, or CALL; the first two mean Jump/Branch to SubRoutine) pushes an address onto the stack -- this is how the CPU knows where it came from. That means you can't just push something onto the stack before calling a routine and pop it from within the routine.
References