【关于NES汇编】
我的天,你正准备学习用汇编写NES程序?那么,如果你真想这么做,本文应该有所帮助。也许你已经读过我的正在进行中的GameBoy高级汇编系列文章。在我的GBA汇编教程中,指出你在进行汇编编程前应该先了解GBA C语言编程。我对于NES汇编也这样说,但是针对NES CPU没有好的C编译器。所以我只想说,写NES代码前要了解点GBA汇编或Intel 汇编,因为NES相比前面两者有点难。
我们将使用NESASM.exe作为我们的汇编器。可以从这里下载(http://patater.com/gbaguy/nesasm.zip)。下载后解压到C:\nesasm或者你喜欢的其他地方。很好,压缩包内也有几个其他工具,我们会用到的。但在我们编码之前,我们需要知道我们的老(真的很老)朋友:任天堂娱乐系统(Nintendo Entertainment System,NES)。
【关于NES】
NES是一个很复杂的8位机。是的,NES是一个8位系统如果你还不知道的话。NES使用定制的摩托罗拉6502处理器,更接近Intel x86芯片,而不像ARM系列芯片。NES在我诞生前发布的,所以我不确定那到底是什么时候(估计20世纪70年代末)(我才15岁)。
关于图片处理需求,NES有一个图片处理单元(Picture Processng Unit,PPU)芯片,我们通过内存映射寄存器间接对它编程(类似于GBA那样,但仍有很大区别)。
在精灵(Sprites)的世界里,NES的确有硬件精灵,但和GBA处理精灵的方法不同。
没有结合代码很难解释清楚,所以让我们一起学习6502汇编如何?
【NES汇编语言】
CPU所有寄存器中,我们最常打交道的3个是:
A:累加器,所有数学操作默认使用这个寄存器;
X:索引寄存器,用于内存寻址的索引;
Y:索引寄存器,同上。
注意所有3个寄存器都可放入数值或者内存中的数据。
lda #$50; A中加载0x50
ldx #$60; X中加载0x60
ldy #$70; Y中加载0x70
注意到这些,嗯,都是8位寄存器。你可能奇怪这些#$是神马?听哥告诉你,'#'表示立即数,就是数,不是地址。'$'表示数字以十六进制表示。
同样滴,'%'表示二进制表示,而啥都没有那就是十进制数。
例如:
lda #%00100011; A中加载二进制数
ldx #50; X中加载十进制数50
ldy #$50; Y中加载十六进制50(和上面50差30,自己算)
我希望这已经清楚了。如果不清楚,直接email作者[email protected]。
【存储器寻址】
把'#'去掉后的数字,将会被汇编器解释为地址。地址通常为16bit十六进制数,所以从内存加载一个值到寄存器,我们这样做:
lda $2002; 将内存地址0x2002处的值加载到A
ldx 2002; 将内存地址2002处的值加载到X
ldy 2002; 将内存地址2002处的值加载到Y
不难吧?哈!
现在你需要知道下一条指令。
【保存值到内存】
下一条指令是ST?,问号处可填入3个寄存器名。这个操作与LD?是相反的操作。但ST?不能接受一个立即数作为参数。
sta $2004; 将A的值保存到内存地址0x2004处
sty $2002; 将Y的值保存到0x2002处
stx $FF; 将X的值保存到0x00FF处
注意到没?地址经常用十六进制表示。地址不足16bit的将会在高位补0凑够16bit。
另外注意我们目前所做的叫做直接寻址,顾名思义,指令里面就给出了实际操作地址。
【今天回顾】
今天我们学习了两条指令,别小看这两条指令,它们将占用我们代码的50%……伟大的成就,不是么?