Accumulator: A
Index Register: X , Y
变址寻址中 存放地址偏移量
也常被当作计数器用
还可以作为 通用寄存器 用于暂存数据
Stack Pointer: S , 或 SP
系统堆栈区: 1页 , 0x100~0x1FF
初始值为 $ff, 指向 $01ff, 也即栈底;
当有值入栈, 值存入当前SP位置,同时 SP=SP-1, 即为 $fe, 指向$01fe
当有值出栈, SP=SP+1, 指向栈顶, 然后弹出值
SP 总是指向一个 空slot
Processor Status: P
C : Carry 进位, 加法有进位 置1,减法有进位 置0
Z : Zero , 1 表示运算结果为0
I : Interrupt , 表明是否允许中断 0允许.
D : Decimal Mode 十进制运算标志,为1则后续的加/减法运算都是十进制
B : indicates that the break operation has been called
d5 is unused
V : Overflow , 1 表示有溢出
如果把 数据看成 signed 有符号的, 那么当
Positive + Positive = Negative
Negative + Negative = Positive
这两种情况发生时, 会被处理成溢出
P+P=P, N+N=N 是正常情况 没有溢出, P+N 则不会出现溢出
so V = (A^R) & ~(A^M)
N : Negative Flag, 复制 运算结果的最高位到 N
D7
D6
D5
D4
D3
D2
D1
D0
N
V
B
D
I
Z
C
NMI : $FFFA $FFFB
用于和PPU通信
使用 2000~2007 8个寄存器,实现对 VRAM,字符发生器,和PPU 内部色彩发生器的控制。
IRQ : $FFFE $FFFF
$FFFC $FFFD
开机后,系统自动执行 $FFFC $FFFD 指定的地址
地址区间
用途
$0000 ~ $07FF
2K VRAM,前2页分别系统0页和系统堆栈区,第3页一般作为卡通定义区(可设置)
$0800 ~ $1FFF
6K 空区,VRAM的镜像
$2000 ~ $3FFF
8K, 与PPU相连的I/O区
$4000 ~ $5FFF
8K, CPU的I/O区
$6000 ~ $7FFF
8K, 空区,根据需要扩充为SRAM区
$8000 ~ $FFFF
32K, PROM
地址区间
用途
$0000 ~ $0FFF
4K, 图形库第一区,256个卡通tile
$1000 ~ $1FFF
4K, 图形库第二区,256个背景,字符tile
$2000 ~ $23FF
1K, 背景00页屏幕映射区 960+64 , 64=((960/16)+7)&(~7)
$2400 ~ $27FF
1K, 背景10页屏幕映射区 (right to 00)
$2800 ~ $2BFF
1K, 01页
$2C00 ~ $2FFF
1K, 11页
$3000 ~ $3EFF
4K-256, 空区, 背景页的镜像
$3F00 ~ $3FFF
256B, 16B 背景页配色代码定义区 + 16B 卡通页配色代码定义区 + 剩余空区镜像
因为VRAM 只有2K,所以只能操作2个背景页, 另外两个背景页则是 镜像(水平镜像或垂直镜像)
实际上,还有一种 four screen mirroring, 但需要昂贵的硬件支持
背景显示窗口位置
卡通/背景使用的字模首地址 $0000 或 $1000
卡通大小控制
背景/卡通显示控制
卡通定义页面的首地址
读取 PPU数据
$2004 CPU向 PPU卡通页面属性工作区 写数据?
13种寻址方式,56条基本指令
主要特点
支持0页寻址: CPU可以直接访问 $00~$FF
指令格式统一
指令长度 1-3字节
第一个字节是 操作码;
紧跟着是 操作数 或 操作数地址, 占1-2个字节
外设访问简便
与外设之间交换数据 或 信息采集,采用了 存储器映像方式。
凡事用于 访问存储器的指令 都可以用来访问 外设。
高效的显示方式
对显示的控制 仅通过8个系统软开关 向PPU发布命令。
简单的发声控制
op #$nn
立即数 为两位16进制数, 00~FF
立即寻址方式的指令长度 均为 2个字节
11 条指令
LDA, LDX, LDY
ADC, SBC
AND, ORA, EOR
CMP, CPX, CPY
2 绝对寻址 Absolute Addressing
op $n2n1
, op n1 n2
i.e. LDA $8000
, AD 00 80
($8000) -> A
绝对寻址指令都是 3字节长度
23 条指令
LDA, LDX, LDY
STA, STX, STY
JMP, JSR
INC, DEC
ADC, SBC
AND, ORA, EOR
BIT
ASL, LSR, ROL, ROR
CMP, CPX, CPY
每256个字节为 1页
实际上,存储器的页号 就是存储器的高位地址码
op $nn
i.e. LDA $7F
, A5 7F
($7F) -> A
零页寻址 为2字节指令
21 条指令,
LDA, LDX, LDY
STA, STX, STY
JMP, JSR
INC, DEC
ADC, SBC
AND, ORA, EOR
BIT
ASL, LSR, ROL, ROR
CMP, CPX, CPY
4 隐含寻址 Implied Addressing
操作数 已被 操作码 隐含
单字节指令
隐含寻址 只能在 A,X,Y,S,P 寄存器中进行,不能对存储器 进行操作
25条
PHA, PLA
PHP, PLP
TAX, TXA, TAY, TYA, TXS, TSX
INX, INY, DEX, DEY
SEC, CLC, SED, CLD, SEI, CLI, CLV
RTI, RTS
NOP
BRK
5. 累加器寻址 Accumulator Addressing
操作数在 累计器A中的 寻址方式
i.e. ROR
单字节指令
累加器寻址 也是一种 隐含寻址
4条
6. 绝对X变址寻址 Absolute X-Index Addressing
操作数 的地址由 绝对地址 加上 X寄存器中的数值构成
i.e. ( M + X ) -> A
3字节
15条指令,
LDA, LDX, LDY
STA, STX, STY
JMP, JSR
INC, DEC
ADC, SBC
AND, ORA, EOR
BIT
ASL, LSR, ROL, ROR
CMP, CPX, CPY
7. 绝对Y变址寻址 Absolute Y-Index Addressing
i.e. ( M + Y ) -> A
3字节
9 条指令
LDA, LDX
STA
ADC, SBC
ORA, AND, EOR
CMP
两种情况
Zero page X-indexed addressing
Zero page Y-indexed addressing
2字节指令
i.e. ( M0 + X ) -> A
只能产生 0页地址,超过 部分舍弃掉
如 当 X=$D8时, LDA $80, X
得到的有效地址是 $58 ( 0xD8 + 0x80 = 0x158)
零页X变址寻址指令 , 16条
零页Y变址寻址指令 , 2条
9. 间接寻址 Indirect Addressing
操作数部分 给出的是 实际操作数 所在地址的 地址地位
有效地址的高位 则是 低位单元的下一个单元
三字节指令
只有 1条指令
10. 相对寻址 Relative Addressing
2字节指令, 只适用于 条件转移指令
操作数 为相对地址偏移D, 它实际上就是 无条件转移指令的 跳转步长
操作数的实际地址 是以 本指令的下一条指令的地址作为 基地址,再加偏移量D
8条指令
BNE, BEQ
BCC, BCS
BPL, BMI
BVC, BVS
双字节指令, 操作数为 0页地址
先以 变址寄存器X变址,然后再进行 间接寻址
实际上是 0页X变址, 和 间接寻址 两种方式的结合
只能使用 X寄存器
8 条指令
LDA
STA
ADC, SBC
ORA, AND, EOR
CMP
先在0页 间接寻址,获得16位基地址, 然后用Y 变址寻址, 得到操作数的实际存放地址
实际上是 0页间接寻址 和 绝对Y变址 相结合的一种寻址方式
双字节指令,操作数为 0页地址
变址寄存器只能使用Y寄存器
8条指令
LDA, STA
ADC, SBC
ORA, AND, EOR
CMP
http://www.llx.com/~nparker/a2/opcodes.html
http://c64os.com/post/6502instructions#RTS
https://www.masswerk.at/6502/6502_instruction_set.html
大多数 明确引用内存位置的指令都具有 aaabbbcc 的形式
The aaa and cc bits determine the opcode
and the bbb bits determine the addressing mode
Instructions with cc = 01 are the most regular, aaa bits detemine the opcode as follows
aaa
opcode
000
ORA
001
AND
010
EOR
011
ADC
100
STA
101
LDA
110
CMP
111
SBC
And the addressing mode (bbb) bits:
bbb
addressing mode
000
(zero page,X)
001
zero page
010
#immediate
011
absolute
100
(zero page),Y
101
zero page,X
110
absolute,Y
111
absolute,X
·
ORA
AND
EOR
ADC
STA
LDA
CMP
SBC
(zp,X)
01
21
41
61
81
A1
C1
E1
zp
05
25
45
65
85
A5
C5
E5
#
09
29
49
69
·
A9
C9
E9
abs
0D
2D
4D
6D
8D
AD
CD
ED
(zp),Y
11
31
51
71
91
B1
D1
F1
zp,X
15
35
55
75
95
B5
D5
F5
abs,Y
19
39
59
79
99
B9
D9
F9
abs,X
1D
3D
5D
7D
9D
BD
DD
FD
cc = 10 instructions are completely different set of opcodes:
aaa
opcode
000
ASL
001
ROL
010
LSR
011
ROR
100
STX
101
LDX
110
DEC
111
INC
The addressing modes are similar to the 01 case, but not quite the same:
Note that bbb = 100 and 110 are missing.
Also,
with STX and LDX, "zero page,X" addressing becomes "zero page,Y"
and with LDX, "absolute,X" becomes "absolute,Y".
只有 cc = 10 指令有 累加器寻址( 4条 ) ,到现在已经出现了10种寻址方式
bbb
addressing mode
000
#immediate
001
zero page
010
accumulator
011
absolute
101
zero page,X
111
absolute,X
These fit together like this:
·
ASL
ROL
LSR
ROR
STX
LDX
DEC
INC
#
A2
zp
06
26
46
66
86
A6
C6
E6
A
0A
2A
4A
6A
abs
0E
2E
4E
6E
8E
AE
CE
EE
zp,X/zp,Y
16
36
56
76
96
B6
D6
F6
abs,X/abs,Y
1E
3E
5E
7E
BE
DE
FE
Next, the cc = 00 instructions. Again, the opcodes are different:
aaa
opcode
001
BIT
010
JMP
011
JMP (indirect)
100
STY
101
LDY
110
CPY
111
CPX
The addressing modes are the same as the 10 case, except that accumulator mode (010) is missing.
这里出现一条 唯一的间接寻址指令 JMP indirect, 到现在已经出现了11种寻址方式
JMP indirect 跨页寻址有bug,会意外复位
bbb
addressing mode
000
#immediate
001
zero page
011
absolute
101
zero page,X
111
absolute,X
And here's how they fit together:
·
BIT
JMP
JMP indirect
STY
LDY
CPY
CPX
#
A0
C0
E0
zp
24
84
A4
C4
E4
abs
2C
4C
6C
8C
AC
CC
EC
zp,X
94
B4
abs,X
BC
so this is the reason why accumulator mode is missing :
if accumulator mode (bbb = 010) were available,
"LDY A" would be A8, which falls in the slot occupied by TAY,
but the pattern breaks down elsewhere--TYA is 98, rather than 88,
which we would expect it to be if it corresponded to the nonexistant "STY A".
No instructions have the form aaabbb11.
The conditional branch instructions all have the form xxy10000 .
The flag indicated by xx is compared with y (flag) , and the branch is taken if they are equal.
note: cc==00 instruction has no bbb=100 mode, so it can be used for conditional branch
xx
flag
00
negative
01
overflow
10
carry
11
zero
This gives the following branches:
BPL
BMI
BVC
BVS
BCC
BCS
BNE
BEQ
10
30
50
70
90
B0
D0
F0
interrupt and subroutine instructions:
(JSR is the only absolute-addressing instruction that doesn't fit the aaabbbcc pattern.)
xxx00000, cc = 00 的 立即数寻址 bbb=000 没有使用 000,001,010,011
BRK
JSR abs
RTI
RTS
00
20
40
60
Other single-byte instructions (大部分的隐含寻址指令):
xxx01000 , cc = 00 没有 bbb=010 形式
PHP
PLP
PHA
PLA
DEY
TAY
INY
INX
08
28
48
68
88
A8
C8
E8
xxx11000 , cc = 00 没有 bbb=110 形式
CLC
SEC
CLI
SEI
TYA
CLV
CLD
SED
18
38
58
78
98
B8
D8
F8
xxx01010 , cc = 10 没有 bbb=010 形式
TXA
TXS
TAX
TSX
DEX
NOP
8A
9A
AA
BA
CA
EA
立即数/内存单元 数据 送入 寄存器
LDA , Load Accumulator
LDX , Load index register X
LDY , Load index register Y
寄存器数据 送入 内存单元 (注意:不影响标志寄存器)
寄存器之间数据传送
TAX (AA) , Transfer A to X , A -> X
TXA (8A) , X -> A
TAY (A8) , A -> Y
TYA (98) , Y -> A
TXS (9A) , X -> S
TSX (BA) , S -> X
堆栈指令
A 内容进出栈 // 隐含寻址开始
PHA (48) , PusH Accumulator , A push -> 堆栈
PLA (68) , PuLl Accumulator, 堆栈 pop -> A
P 内容进出栈
PHP (08) , PusH Processor status
PLP (28) , PuLl Processor status
移位指令
算术左移 , Arithmetic Shift Left
ASL shifts all bits left one position.
0 is shifted into bit 0 , and the original bit 7 is shifted into the Carry.
[C NN]
ASL
D7 -> C
0 -> D0
<=>
x * 2
逻辑右移 4E , Logical Shift Right
LSR
D0 -> C
0 -> D7
<=>
无符号数 / 2
循环左移 2E , ROtate Left
ROL shifts all bits left one position.
The Carry is shifted into bit 0 and the original bit 7 is shifted into the Carry.
[ C NN C ]
循环右移动 6E , ROtate Right
带进位加法
ADC , ADd with Carry
A + M + C -> A
带进位减法
SBC , SuBtract with Carry
A - M - C̅ -> A
A - M - (1-C) => A+ -M -1+C => A + ~M+1-1 +C => A + ~M + C // something like ADC
比较指令
CMP , 计算 A - XX ,仅改变 标志寄存器 N,Z,C
CPX , ComPare with index register X , 计算 X - XX
CPY , ComPare with index register Y , 计算 Y - XX
+1 指令
-1 指令
标志位指令
P 进位标志 设置/清除
SEC (38) , C = 1
CLC (18) , C = 0
P 十进制运算标志 设置/清除
SED (F8) , D = 1
CLD (D8) , D = 0 // 41
The Decimal Flag (D) is bit 3 of the Processor Status Register.
The NES does not use decimal mode, so the bit is usually set to 0.
However, since the opcodes that set and clear the flag are still functional in the NES, you can use this flag to store data.
If the NES did support decimal mode, math would be handled differently when the decimal mode flag was set.
If an ADC or SBC instruction were executed, the source values would be treated as valid BCD (Binary Coded Decimal,
eg. 0x00-0x99 = 0-99) numbers, and the generated result would also be a BCD number.
P 溢出标志位 清除
逻辑运算指令
AND , A & nn -> A
ORA , OR with Accumulator , A | nn -> A
EOR , Exclusive OR , A ^ nn -> A
位测试指令
BIT
M D7 -> N
M D6 -> V
A & M , Z
无条件转移 ( 不影响标志位 )
JMP
跳转到某个地址 继续执行,i.e. 分支语句
条件转移指令
Z标志转移指令
C标志转移指令
BCC 无进位转移 , Branch on Carry Clear
BCS 有进位转移 , Branch on Carry Set
N标志转移指令
BPL 非负转移 , Branch on PLus
BMI 负转移 , Branch on Minus
V标志转移指令
BVC 无溢出转移 , Branch on oVerflow Clear
BVS 溢出转移, Branch on oVerflow SET // 55
子程序指令
转子指令 , Jump to SubRoutine ( 不影响标志位 )
JSR
i.e. function call
JSR pushes the address-1 of the next operation on to the stack
before transferring program control to the following address.
Subroutines are normally terminated by an RTS op code.
返主指令 ,控制子程序返回指令
RTS (60) , ReTurn from Subroutine
RTS pulls the top two bytes off the stack (low byte first)
and transfers program control to that address+1
中断指令
SEI (78) , I = 1
CLI (58) , I = 0
当 I=0时,可屏蔽中断允许,6502响应中断后,将转到可屏蔽中断服务子程序执行程序。
记:SEI 告诉NES我正在处理中断,在我处理完之前,不响应其他可屏蔽中断
中断返回指令 RTI (40) , ReTurn from Interrupt
控制中断处理程序返回, 恢复中断处理前的线场。
当 6502响应中断后,将把 断点地址和标志寄存器P的内容压栈保存, 然后转到服务程序执行。
当 中断服务程序执行完毕后,将通过RTI指令返回,从堆栈弹出断点地址和P, 恢复中断前的现场,继续执行主程序
空操作
NOP (EA)
编程中,一般使用 空操作指令 控制延时 // 47
BRK
BRK causes a non-maskable interrupt and increments the program counter by one. Therefore an RTI will go to the address of the BRK +2 so that BRK may be used to replace a two-byte instruction for debugging and the subsequent RTI will be correct.
00,01,10 系列的空指令, 只有4种寻址方式
001 : zero page
011 : absolute
111 : absolute,X
000 : 只有 00,10 系列指令有
11 系列的空指令, 没有 bbb == 010 的情况