...
人写 MOV A,#09H,机器认 74H 09H。中间发生了什么,以及这两个字节在程序存储器里是怎么排的——想清楚这个,指令周期就顺了。
MOV A,#09H 是给人看的。汇编器的工作就是把它翻译成机器能执行的字节序列:
| 人写的 | 汇编器翻译成 |
|---|---|
MOV A,#09H |
74H 09H |
第一个字节 74H 叫操作码(opcode),它告诉 CPU"要做什么"——这里是"把立即数送进累加器 A"。第二个字节 09H 叫操作数,是"用什么做"——具体的数据 9。
8051 的指令长度是 1、2、3 字节不等,取决于指令需要几个操作数:
NOP ; 00H —— 1 字节
MOV A,#09H ; 74H 09H —— 2 字节
MOV DPTR,#1234H ; 90H 12H 34H —— 3 字节
规律很直白:操作码固定占 1 字节,后面有几个操作数就再跟几个字节。因为 8051 的数据宽度是 8 位,所以每个操作数占 1 字节,16 位地址就拆成高字节 + 低字节两个。
MOV DPTR,#1234H 翻译成 90H 12H 34H。注意这里 12H 在高位、34H 在低位——十六进制数字的书写顺序和字节存放顺序是一致的,都是高位在前。这一点在算跳转地址时特别容易搞混。
程序存储器(ROM)是逐字节编址的。上面的指令连着放,就是这样:
| 地址 | 内容 | 对应 |
|---|---|---|
0000H |
74H |
MOV A,#09H 的操作码 |
0001H |
09H |
立即数 09H |
0002H |
90H |
MOV DPTR,#1234H 的操作码 |
0003H |
12H |
地址高字节 |
0004H |
34H |
地址低字节 |
执行到 0000H 时,PC 指向下一条指令的起始地址 0002H——PC 自动加上了本条指令的字节数,不是简单地加 1。
这就是为什么 PC 的递增量等于"指令长度"。理解了这一点,"为什么 3 字节指令要花更多机器周期"也就顺理成章了:取指本身就要多访问几次存储器。
把上面的事情拆成 CPU 内部的三个动作:
74H74H 是"取立即数送 A",知道后面还要再读一个字节09H 送进累加器 A,PC 指向 0002H一条 MOV A,#09H 走完这三步,就叫一个指令周期。
想看这三步在 CPU 内部具体是怎么走的,可以直接对着 8051 指令查表动画 点单步,每一阶段寄存器和 RAM 面板都会实时刷新;也可以看 单片机工作过程 的课件原片,那里有完整的结构图讲解。
B. 直接写 HTML:...