6502 共有 13 种寻址模式:
A:寄存器寻址。指令形式为 OPC A
;目标数据位于 A 寄存器中,属于隐含寻址;使用这种寻址模式的指令都是 1 个字节长度,需要 2 个时钟周期
abs:绝对地址寻址。指令形式为 OPC $LLHH
;目标数据位于绝对地址 $HHLL
处
abs,X:X 变址绝对地址寻址。指令形式为 OPC $LLHH,X
;操作数是 16 位基址;有效地址由基址加上 X 寄存器中的值计算得到
abs,Y:X 变址绝对地址寻址。指令形式为 OPC $LLHH,Y
;操作数是 16 位基址;有效地址由基址加上 Y 寄存器中的值计算得到
#:立即数寻址。指令形式为 OPC #$BB
;目标数据即操作数 BB
impl:隐含寻址。目标数据由指令码决定
ind:间接寻址。指令形式为 OPC ($LLHH)
;操作数是 16 位间接地址; 有效地址是位于间接地址处的 16 位内容;读取有效地址时,不考虑跨页
X,ind:X 变址间接寻址。指令形式为 OPC ($LL,X)
;操作数是 8 位间接地址基址; 基址与 X 寄存器的值进行无进位加法后得到间接地址,有效地址是位于间接地址处的 16 位地址;读取有效地址时,不考虑跨页
ind,Y: 间接地址 Y 变址寻址。指令形式为 OPC ($LL),Y
;操作数是一个 8 位间接地址;$LL
处存储的是 16 位基址,基址加上 Y 寄存器的值得到有效地址;读取 16 位基址时,不考虑跨页
rel:相对寻址。指令形式为 OPC $BB
;操作数 BB
为有符号数,表示偏移;目标地址由 PC 加上 BB
得到
zpg:零页寻址。指令形式为 OPC $LL
;操作数是一个 8 位绝对地址,目标数据位于 $00LL
处
zpg,X:零页 X 变址寻址。指令形式为 OPC $LL,X
;操作数是一个 8 位基址;有效地址由基址与 X 寄存器的值进行无进位加法后得到
zpg,Y:零页 Y 变址寻址。指令形式为 OPC $LL,Y
;操作数是一个 8 位基址;有效地址由基址与 Y 寄存器的值进行无进位加法后得到
6502 采用小端序,读取 16 位地址时,先读取到的是低 8 位,然后是高 8 位
我把每个寻址模式的时序整理成了表格,以便清晰地看出 CPU 内每个时钟周期的工作状态,对于理解 6502 的工作原理应该有所帮助。表格中的单元格如果为空白,表示对应的组件没有被修改。需要注意的是,以下时序只适用于正常指令(官方指令)。非法指令在解码时和执行时会激活额外的信号线,导致同样的寻址模式会多做一些事情或者同样的寻址模式却有不同的时长,往往需要单独总结。
我还做了一个网页,可以查询每个指令的时序和详细信息,点击这里 体验。
zpg
Cycle
ADH
ADL
IPC
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取有效地址
T2
0
DL
0
读取目标数据
OPC = RD(PC++);
EA = RD(PC++);
zpx
Cycle
ADH
ADL
IPC
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取基址
T2
0
DL
0
X
DL
0
加上 X 寄存器中的偏移,计算有效地址
T3
ADD
0
读取目标数据
OPC = RD(PC++);
EA = RD(PC++) + X;
zpy
Cycle
ADH
ADL
IPC
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取基址
T2
0
DL
0
Y
DL
0
加上 Y 寄存器中的偏移,计算有效地址
T3
ADD
0
读取目标数据
OPC = RD(PC++);
EA = RD(PC++) + Y;
abs
Cycle
ADH
ADL
IPC
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取有效地址的低 8 位
T2
PCH
PCL
1
0
DL
0
读取有效地址的高 8 位
T3
DL
ADD
0
读取目标数据
OPC = RD(PC++);
EA = WORD(RD(PC + 1 ), RD(PC));
PC += 2 ;
abx
Cycle
ADH
ADL
IPC
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取基址的低 8 位
T2
PCH
PCL
1
X
DL
0
读取基址的高 8 位, 加上 X 寄存器中的偏移
T3
DL
ADD
0
0
DL
ACR
读取目标数据,处理跨页。 若不跨页 (ACR = 0),则跳过 T4 周期
T4
ADD
0
再次读取目标数据
OPC = RD(PC++);
EA = WORD(RD(PC + 1 ), RD(PC)) + X;
PC += 2 ;
aby
Cycle
ADH
ADL
IPC
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取基址的低 8 位
T2
PCH
PCL
1
Y
DL
0
读取基址的高 8 位, 加上 Y 寄存器中的偏移
T3
DL
ADD
0
0
DL
ACR
读取目标数据,处理跨页。 若不跨页 (ACR = 0),则跳过 T4 周期
T4
ADD
0
再次读取目标数据
OPC = RD(PC++);
EA = WORD(RD(PC + 1 ), RD(PC)) + Y;
PC += 2 ;
ind
Cycle
ADH
ADL
IPC
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取间址的低 8 位
T2
PCH
PCL
1
0
DL
0
读取间址的高 8 位
T3
DL
ADD
0
0
ADD
1
读取有效地址的低 8 位,并把间址加 1(无进位)
T4
ADD
0
0
DL
0
读取有效地址的高 8 位
T5
DL
ADD
0
读取目标数据
OPC = RD(PC++);
IA = WORD(RD(PC + 1 ), RD(PC));
EA = WORD(RD(WORD(HI(IA), LO(IA + 1 ))), RD(IA));
PC += 2 ;
inx
Cycle
ADH
ADL
IPC
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取 8 位基址
T2
0
DL
0
X
DL
0
空读,加上 X 寄存器中的偏移计算间址
T3
ADD
0
0
ADD
1
读取有效地址的低 8 位,并把间址加 1(无进位)
T4
ADD
0
0
DL
0
读取有效地址的高 8 位
T5
DL
ADD
0
读取目标数据
OPC = RD(PC++);
IA = BYTE(RD(PC++) + X);
EA = WORD(RD(BYTE(IA + 1 )), RD(IA));
iny
Cycle
ADH
ADL
IPC
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取 8 位间址
T2
0
DL
0
0
DL
1
读取基址的低 8 位,并把间址加 1
T3
ADD
0
Y
DL
0
读取基址的高 8 位,加上 Y 寄存器中的偏移计算有效地址
T4
DL
ADD
0
0
DL
ACR
读取目标数据并处理跨页, 若不跨页 (ACR = 0),则跳过 T5 周期
T5
ADD
0
再次读取目标数据
OPC = RD(PC++);
IA = BYTE(RD(PC++) + X);
EA = WORD(RD(BYTE(IA + 1 )), RD(IA)) + Y;
rel
Cycle
ADH
ADL
IPC
PCH
PCL
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取偏移
T2
PCH
PCL
0
DL
PCL
0
空读,把 PC 加上偏移计算目标地址
T3
ADD
0
ADD
PCH
*
**
处理跨页。 * 若偏移量为正,则 BI 为 0
;否则为 $FF
** 若跨页(ACR = 1)且偏移量为正,则 CI 为 1
;否则为 0
T0
ADD
1
ADD
设置 PC 并读取操作码
OPC = RD(PC++);
OFF = RD(PC++);
PC = PC + OFF;
JMP abs
Cycle
ADH
ADL
IPC
PCH
PCL
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取有效地址的低 8 位
T2
PCH
PCL
0
0
DL
0
读取有效地址的高 8 位
T0
DL
ADD
1
DL
ADD
设置 PC 读取操作码
OPC = RD(PC++);
EA = WORD(RD(PC + 1 ), RD(PC));
PC = EA;
JMP ind
Cycle
ADH
ADL
IPC
PCH
PCL
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取间址低 8 位
T2
PCH
PCL
1
0
DL
0
读取间址高 8 位
T3
DL
ADD
0
0
ADD
1
读取有效地址低 8 位,把间址加 1 (无进位)
T4
ADD
0
0
DL
0
读取有效地址高 8 位
T0
DL
ADD
1
DL
ADD
设置 PC 读取操作码
OPC = RD(PC++);
IA = WORD(RD(PC + 1 ), RD(PC));
EA = WORD(RD(WORD(HI(IA), LO(IA + 1 ))), RD(IA));
PC = EA;
JSR abs
Cycle
ADH
ADL
IPC
PCH
PCL
S
AI
BI
CI
DOR
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
读取有效地址的低 8 位
T2
$01
S
0
DL
0
S
0
将读到的有效地址低 8 位保存到 S 寄存器中,将原本 S 寄存器的内容保存到 ALU 中
T3
$01
ADD
0
$FF
ADD
0
PCH
将 PCH 压栈
T4
$01
ADD
0
$FF
ADD
0
PCL
将 PCL 压栈
T5
PCH
PCL
1
读取有效地址的高 8 位
T0
DL
S
1
DL
S
ADD
设置 PC,读取操作码,并从 ALU 中恢复 S 寄存器
OPC = RD(PC++);
EA = RD(PC++);
WR(S--, PCH);
WR(S--, PCL);
EA = WORD(RD(PC++), LO(EA));
PC = EA;
BRK
Cycle
ADH
ADL
IPC
PCH
PCL
S
AI
BI
CI
DOR
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
0
空读
T2
$01
S
0
$FF
S
0
PCH
将 PCH 压栈
T3
$01
ADD
0
$FF
ADD
0
PCL
将 PCL 压栈
T4
$01
ADD
0
$FF
ADD
0
P
将 P 寄存器的内容压栈
T5
$FF
$FE
0
ADD
读取中断向量的低 8 位
T6
$FF
$FF
0
0
DL
0
读取中断向量的高 8 位
T0
DL
ADD
1
DL
ADD
设置 PC 并读取操作码
OPC = RD(PC++);
WR(S--, PCH);
WR(S--, PCL);
WR(S--, P);
PC = WORD(RD(0xFFFF ), RD(0xFFFE ));
RTI
Cycle
ADH
ADL
IPC
PCH
PCL
S
P
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
空读
T2
$01
S
0
0
S
1
空读,栈指针加 1
T3
$01
ADD
0
0
ADD
1
从栈顶读 P 寄存器的内容,栈指针加 1
T4
$01
ADD
0
DL
0
ADD
1
从栈顶读 PCL 的内容,栈指针加 1
T5
$01
ADD
0
ADD
0
DL
0
从栈顶读 PCH 的内容
T0
DL
ADD
1
DL
ADD
设置 PC 并读取操作码
OPC = RD(PC++);
P = RD(++S);
PCL = RD(++S);
PCH = RD(++S);
RTS
Cycle
ADH
ADL
IPC
PCH
PCL
S
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
1
空读
T2
$01
S
0
0
S
1
空读,栈指针加 1
T3
$01
ADD
0
0
ADD
1
从栈顶读 PCL,栈指针加 1
T4
$01
ADD
0
ADD
0
DL
0
从栈顶读 PCH
T5
DL
ADD
1
DL
ADD
空读,设置 PC 指针
T0
PCH
PCL
1
读取操作码
OPC = RD(PC++);
PCL = RD(++S);
PCH = RD(++S);
PC++;
PHA, PHP
Cycle
ADH
ADL
IPC
S
AI
BI
CI
DOR
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
0
空读
T2
$01
S
0
$FF
S
0
A/P
将 A 或 P 寄存器的内容压栈
T0
PCH
PCL
1
ADD
读取操作码
OPC = RD(PC++);
WR(S--, A);
PLA, PLP
Cycle
ADH
ADL
IPC
A/P
S
AI
BI
CI
说明
T0
PCH
PCL
1
读取操作码
T1
PCH
PCL
0
空读
T2
$01
S
0
0
S
1
空读,栈指针加 1
T3
$01
ADD
0
ADD
从栈顶读 A 或 P 的内容
T0
PCH
PCL
1
DL
读取操作码,设置 A 或 P 寄存器
OPC = RD(PC++);
A = RD(++S);
参考
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业