【关于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作者vbnetprogramer@hotmail.com。

【存储器寻址】

把'#'去掉后的数字,将会被汇编器解释为地址。地址通常为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%……伟大的成就,不是么?