



本节给出了6502处理器支持的指令类型。讨论6502的目的是介绍处理器体系结构所涉及的指令集相关概念,这种处理器体系结构比现代32位和64位处理器体系结构要简单得多。
在6502中,load(加载)和store(存储)指令分别是将系统内存的数据加载到寄存器中,以及将寄存器数据存储到系统内存中。在6502体系结构中,LDA、LDX和LDY指令是把内存中的8位数据加载到指定的寄存器中。6502中的LDA指令支持所有的寻址方式,而LDX和LDY支持有限的寻址方式:立即数寻址和绝对寻址和绝对索引寻址。
在每条指令执行完毕后,N标志表示加载的数值是否为负数(也就是第7位等于1),Z标志表示数值是否为0。
STA、STX和STY指令是将指定寄存器的内容存储到内存中。除了不支持立即寻址方式外,每条store指令都支持与load指令相同的寻址方式。这些指令通过更改N标志和Z标志来反映存储到内存中的数据的特征。
这些指令将A寄存器、X寄存器和Y寄存器中存放的8位数据复制到另一个寄存器中,它们使用的是 隐含寻址方式 (implied addressing mode)。隐含寻址方式指的是每条指令的源地址和目标地址都是由指令操作码直接表示的。
TAX指令是将A寄存器的内容复制到X寄存器中。TAY、TXA和TYA等指令在指令助记符指定的寄存器对之间执行与TAX指令相同的操作。这些指令执行也能够更改N标志和Z标志。
TXS指令是将X寄存器中的值复制到栈指针(S)寄存器中,该指令在系统启动期间用来初始化S寄存器。TSX指令是将S寄存器中的栈指针复制到X寄存器中,且TSX指令的执行也能更改N标志和Z标志,而TXS指令不影响任何标志。
PHA指令将A寄存器的内容压入栈,PHP指令将处理器标志作为8位数据字压入栈。这些指令都不影响处理器标志。将数据压入栈包括以下步骤:先把$100加到S寄存器中,把数据写入由S寄存器中的内容指明的内存单元中,然后对S寄存器的内容进行递减操作。
PLA指令和PLP指令分别将从栈中弹出的数据存入A寄存器和标志寄存器。一个数据弹出栈时,首先需要将S寄存器进行递增操作,并将$100加到寄存器S中,然后从S寄存器中的内容指明的内存单元中读出数据,最后将读出的数据传送到目标寄存器中。
PLA指令能够更改N标志和Z标志。PLP指令会根据从栈中弹出的值设置或清除7个处理器标志中的6个标志。只有在中断或PHP指令将处理器标志寄存器的副本压入栈时,B(中断)标志才有意义。这会将BRK指令与硬件中断请求区分开。PHP和BRK指令都将B标志位(第4位)置位之后再将标志寄存器压入栈。
通过处理器中断请求(Interrupt Request,
)和不可屏蔽中断(Non-Maskable Interrupt,
)引脚产生的硬件中断,将会把B标志位清零之后的标志寄存器压入栈。本章稍后将讨论中断处理和BRK指令。
如前所述,加法运算和减法运算由ADC和SBC指令实现。A寄存器中存放每条指令的左操作数,也用于存放运算结果。指令的右操作数支持所有的寻址方式。同样地,这两条指令能够更改Z、C、N和V等反映运算结果特征的标志。
INC和DEC指令通过把指定内存单元中的数据加1或减1进行递增或递减,运算结果依然存储在相同的内存单元中。这两条指令支持绝对寻址和绝对索引寻址,并根据运算结果来更改N标志和Z标志。
正如助记符的含义所示,INX、DEX、INY和DEY指令将对X寄存器或Y寄存器的数据进行递增或递减。这些指令也会更改N标志和Z标志。
CMP指令通过从A寄存器中减去操作数来进行比较。CMP指令的行为与SEC后面跟一条SBC指令的指令序列非常相似。减法结果的特征通过N、Z和C等标志来反映。CMP指令和SBC指令之间的区别如下:
● CMP指令会丢弃相减的结果(即CMP指令不会影响A寄存器的值)。
● 如果设置了D标志,CMP指令就不使用十进制模式。
● CMP指令不影响V标志的值。
● CMP指令支持所有的寻址方式。
如助记符的含义所示,CPX和CPY指令与CMP指令相似,它们的不同之处在于X寄存器或Y寄存器被用作左操作数,并且右操作数只支持绝对寻址和绝对索引寻址方式。
AND、EOR和ORA指令对A寄存器和操作数按位执行与、异或和或运算,结果保存在A寄存器中。这些指令会影响Z和N标志,以此来反映运算结果,而且支持所有的寻址方式。
ASL指令将操作数左移一位,空出来的最低有效位补0,最高有效位的值移入C标志中,这等同于将A寄存器的值乘以2,并将结果的最高有效位(即第9位)放在C标志中。
与ASL指令相似,LSR指令将操作数右移一位,空出来的最高有效位补0,最低有效位的值移入C标志中,这等同于将无符号操作数除以2,并将得到的余数放在C标志中。
ROL和ROR指令分别将A寄存器左移和右移一位。把原来存储在C标志的值移入由移位空出的位置,从A寄存器中移出的那一位存储在C标志中。
ASL、LSR、ROL和ROR指令支持 累加器寻址方式 (accumulator addressing mode),该寻址方式用A寄存器作为操作数。与指令ASL A一样,都是使用特殊的操作数值“A”来指定此寻址方式。这4条指令同样也支持绝对寻址和绝对索引寻址方式。
BIT指令在操作数和A寄存器之间执行按位与运算,根据运算结果更新Z标志,并丢弃运算结果。将内存单元的第7位和第6位分别复制到N和V标志中。该指令仅支持绝对寻址方式。
JMP指令将操作数加载到PC寄存器中,并从PC寄存器中新内容指定的位置继续执行。该指令的目标地址是指向6502的16位地址空间中任何位置的两字节绝对地址。
● BCC和BCS指令的分支是否执行分别取决于C标志的清除与置位。
● BNE和BEQ指令的分支是否执行分别取决于Z标志的清除与置位。
● BPL和BMI指令的分支是否执行分别取决于N标志的清除与置位。
● BVC和BVS指令的分支是否执行分别取决于V标志的清除与置位。
条件分支指令使用的是 相对寻址方式 (relative addressing mode),使用从分支指令之后的指令地址开始的有符号8位偏移量(-128到+127之间)。
JSR指令将紧跟其后的指令的地址(减1)压入栈,然后将16位操作数指定的地址加载到PC寄存器中,并从该位置的指令继续执行。
RTS指令用于结束一个子程序。从栈中弹出要返回的PC值(减1)并将其加载到PC寄存器中。RTS指令从栈中弹出PC寄存器之后加1,然后用作下一条要执行的指令的地址。
处理器标志指令直接对标志进行置位或清除操作。
● SEC和CLC指令分别置位和清除C标志。
● SED和CLD指令分别置位和清除D标志。
● CLV指令清除V标志。目前还没有指令可以置位V标志。
与中断相关的指令允许处理器管理外部中断的处理,并生成软件触发的中断。外部中断有两种类型:可屏蔽中断和不可屏蔽中断。每种类型的中断都是通过6502处理器上各自对应的输入引脚触发的。
可屏蔽中断可以通过设置处理器的I标志来禁用。当中断被屏蔽时,处理器将忽略相关的输入引脚。顾名思义,不可屏蔽中断不能被禁用,当相关引脚上发生适当的信号转换时,总是触发处理器进行相应的中断处理。我们将在3.5节详细介绍中断处理。
SEI和CLI指令分别对I标志进行置位和清除。当I标志被置位时,就会禁用可屏蔽中断。
BRK指令能触发一个不可屏蔽中断。BRK指令之后两个字节的内存地址被压入栈,然后处理器标志寄存器也入栈。之后在PC寄存器中加载中断处理程序的入口地址,该地址从内存地址$FFFE~$FFFF中读取。最后开始执行中断处理程序。
BRK指令不会更改任何寄存器内容(栈指针除外)或处理器标志。如果压入栈的标志寄存器B位被置位,则表示中断是BRK指令引发的。
RIT指令从中断处理程序返回。该指令从栈中恢复处理器标志和PC寄存器。恢复处理器标志后,B标志不再有意义,应将其忽略。
中断处理和BRK指令的使用详见3.5节。
NOP指令(通常称为“no-op”)除了把PC寄存器的内容指向后续的指令外,不做任何事情。
NOP指令有时在程序开发过程中被用作调试工具。例如,用$EA字节填充指令的内存地址,可以有效地注释掉一条或多条指令。在6502中,$EA是NOP指令操作码的十六进制编码。