Memory接口
我们都已经知道,程序必须加载到内存中才能被CPU执行。内存按照读写方式大致可以分为两种:ROM是只读的,RAM可以读也可以写。不过在真正的计算机中,CPU并不关心自己读写的是RAM还是ROM,因为CPU是通过总线(BUS)和内存间接沟通的。正是因为这样,6502只需要知道自己能够通过一个16比特的地址总线读写64K大小的内存就够了。至于这些内存到底是RAM还是ROM,是嵌在游戏机内部还是游戏卡上,都不重要。下面是Memory接口的代码:
public interface Memory {
// Read one byte.
public short read(int address);
// Write one byte.
public void write(int address, short value);
}
6502是8比特CPU,也就是说,每一条指令只能够操作一个8比特整数,所以用一个byte[]就可以模拟内存了。但是考虑到大部分时候6502操作的都是无符号整数,而Java语言的byte表示的则是有符号整数,用byte会带来诸多不便,所以就使用了short来表示无符号8比特整数。
MOS6502
下面是6502模拟器的部分代码,emulate()方法执行一条指令,暂时还没实现,其他细节稍后介绍:
public class MOS6502 {
private final Registers registers = new Registers();
private final Flags flags = new Flags();
private Memory memory;
public Registers getRegisters() {
return registers;
}
public Flags getFlags() {
return flags;
}
public Memory getMemory() {
return memory;
}
public void setMemory(Memory memory) {
this.memory = memory;
}
// Execute one instruction.
public void emulate() {
// TODO
}
}
内存读写
为了方便起见,MOS6502实现了一对儿内存读写方法,这样可以省去每次内存读写操作前的getMemory()方法调用:
public class MOS6502 {
...
// Read one byte from memory
public short read(int address) {
return memory.read(address);
}
// Write one byte into memory
public void write(int address, short value) {
memory.write(address, value);
}
...
}
栈操作
前面的文章提到过,6502可以操作一个256字节大小的栈,这个栈位于内存的$0100到$01FF之间。下面是push()和pull()方法的实现:
public class MOS6502 {
...
// Push one byte into stack
public void push(int value) {
int oldSp = registers.getSP();
write(oldSp, (short) value);
int newSp = oldSp - 1;
registers.setSP(newSp);
}
// Pull one byte from stack
public short pull() {
int newSp = registers.getSP() + 1;
registers.setSP(newSp);
return read(newSp);
}
...
}