25 - MOV 指令

---- 整理自B站UP主 踌躇月光 的视频

1. 指令系统设计

指令 IR 8 位程序状态字 4 位微程序周期 4 位

2. MOV 指令

MOV A, 5; 立即寻址
MOV A, B; 寄存器寻址
MOV A, [5]; 直接寻址
MOV A, [B]; 寄存器间接寻址

MOV A, B

ADD A, 5

NOT A

HLT
  • 二地址指令,MOV A,B
    • 1xxx[aa][bb]
  • 一地址指令,NOT A
    • 01xxxx[aa]
  • 零地址指令,HLT
    • 00xxxxxx
立即寻址 = 0
寄存器寻址 = 1
直接寻址 = 2
寄存器间接寻址 = 3

3. 实现

3.1 CPU 电路图

请添加图片描述

3.2 代码实现


MSR = 1
MAR = 2
MDR = 3
RAM = 4
IR = 5
DST = 6
SRC = 7
A = 8
B = 9
C = 10
D = 11
DI = 12
SI = 13
SP = 14
BP = 15
CS = 16
DS = 17
SS = 18
ES = 19
VEC = 20
T1 = 21
T2 = 22


MSR_OUT = MSR
MAR_OUT = MAR
MDR_OUT = MDR
RAM_OUT = RAM
IR_OUT = IR
DST_OUT = DST
SRC_OUT = SRC
A_OUT = A
B_OUT = B
C_OUT = C
D_OUT = D
DI_OUT = DI
SI_OUT = SI
SP_OUT = SP
BP_OUT = BP
CS_OUT = CS
DS_OUT = DS
SS_OUT = SS
ES_OUT = ES
VEC_OUT = VEC
T1_OUT = T1
T2_OUT = T2

_DST_SHIFT = 5

MSR_IN = MSR << _DST_SHIFT
MAR_IN = MAR << _DST_SHIFT
MDR_IN = MDR << _DST_SHIFT
RAM_IN = RAM << _DST_SHIFT
IR_IN = IR << _DST_SHIFT
DST_IN = DST << _DST_SHIFT
SRC_IN = SRC << _DST_SHIFT
A_IN = A << _DST_SHIFT
B_IN = B << _DST_SHIFT
C_IN = C << _DST_SHIFT
D_IN = D << _DST_SHIFT
DI_IN = DI << _DST_SHIFT
SI_IN = SI << _DST_SHIFT
SP_IN = SP << _DST_SHIFT
BP_IN = BP << _DST_SHIFT
CS_IN = CS << _DST_SHIFT
DS_IN = DS << _DST_SHIFT
SS_IN = SS << _DST_SHIFT
ES_IN = ES << _DST_SHIFT
VEC_IN = VEC << _DST_SHIFT
T1_IN = T1 << _DST_SHIFT
T2_IN = T2 << _DST_SHIFT

SRC_R = 2 ** 10
SRC_W = 2 ** 11
DST_R = 2 ** 12
DST_W = 2 ** 13

PC_WE = 2 ** 14
PC_CS = 2 ** 15
PC_EN = 2 ** 16

PC_OUT = PC_CS
PC_IN = PC_CS | PC_WE
PC_INC = PC_CS | PC_WE | PC_EN

CYC = 2 ** 30
HLT = 2 ** 31


# - 二地址指令IR对应
#     - 1xxx [aa][bb]
# - 一地址指令IR对应
#     - 01xx xx[aa]
# - 零地址指令IR对应
#     - 00xx xxxx
ADDR2 = 1 << 7
ADDR1 = 1 << 6

ADDR2_SHIFT = 4
ADDR1_SHIFT = 2

AM_INS = 0 # 立即寻址 instant
AM_REG = 1 # 寄存器寻址
AM_DIR = 2 # 直接寻址 direct
AM_RAM = 3 # 寄存器间接寻址
import pin

FETCH = [
    pin.PC_OUT | pin.MAR_IN,
    pin.RAM_OUT | pin.IR_IN | pin.PC_INC,
    pin.PC_OUT | pin.MAR_IN,
    pin.RAM_OUT | pin.DST_IN | pin.PC_INC,
    pin.PC_OUT | pin.MAR_IN,
    pin.RAM_OUT | pin.SRC_IN | pin.PC_INC,
]

MOV = 0 | pin.ADDR2 # MOV指令定义为 1000 xxxx
ADD = (1 << pin.ADDR2_SHIFT) | pin.ADDR2 # ADD指令定义为 1001 xxxx

NOP = 0
HLT = 0x3f

INSTRUCTIONS = {
    2: { # 二地址指令
        MOV: { # MOV指令寻址方式
            (pin.AM_REG, pin.AM_INS): [ # (寄存器寻址,立即寻址) ==> MOV A,5
                pin.DST_W | pin.SRC_OUT, # 微指令:DST(A)寄存器写,SRC(5)寄存器输出
            ]
        }
    },
    1: {}, # 一地址指令
    0: { # 零地址指令
        NOP: [
            pin.CYC, # 让指令周期清零,跳过这次指令
        ],
        HLT: [
            pin.HLT, # 指令停止
        ]
    }
}

print(bin(MOV))
import os
import pin
import assembly as ASM

dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'micro.bin')

micro = [pin.HLT for _ in range(0x10000)]

def compile_addr2(addr, ir, psw, index):
    global micro
    
    # addr ==> | IR | PSW | CYC |
    # 二地址指令IR对应 ==> 1xxx [aa][bb]
    op = ir & 0xf0
    amd = (ir >> 2) & 3 # [aa] 寻址方式
    ams = ir & 3 # [bb] 寻址方式
    
    INST = ASM.INSTRUCTIONS[2]
    if op not in INST:
        micro[addr] = pin.CYC
        return
    am = (amd, ams)
    if am not in INST[op]:
        micro[addr] = pin.CYC
        return
    
    EXEC = INST[op][am] # 找到IR和寻址方式
    if index < len(EXEC): # 补到FETCH后面
        micro[addr] = EXEC[index]
    else:
        micro[addr] = pin.CYC

# 01xx xx[bb]
def compile_addr1(addr, ir, psw, index):
    pass

# 00xx xxxx
def compile_addr0(addr, ir, psw, index):
    global micro
    
    op = ir

    INST = ASM.INSTRUCTIONS[0]
    if op not in INST:
        micro[addr] = pin.CYC
        return
    
    EXEC = INST[op]
    if index < len(EXEC):
        micro[addr] = EXEC[index]
    else:
        micro[addr] = pin.CYC

for addr in range(0x10000): # 指令集处理
    # | IR | PSW | CYC |
    #   8     4     4
    ir = addr >> 8
    psw = (addr >> 4) & 0xf
    cyc = addr & 0xf
    
    # 先处理 取指指令FETCH
    if cyc < len(ASM.FETCH):
        micro[addr] = ASM.FETCH[cyc]
        continue
    
    addr2 = ir & (1 << 7) # 二地址
    addr1 = ir & (1 << 6) # 一地址
    
    index = cyc - len(ASM.FETCH) # FETCH占据了前面的位置,这里表示FETCH后面
    
    if addr2:
        compile_addr2(addr, ir, psw, index) # 处理二地址
    elif addr1:
        compile_addr1(addr, ir, psw, index) # 处理一地址
    else:
        compile_addr0(addr, ir, psw, index) # 处理零地址

with open(filename, 'wb') as file:
    for var in micro:
        value = var.to_bytes(4, byteorder='little')
        file.write(value)

print('Compile micro instruction finish!!!')

3.3 实验过程

  1. 我们将编译完的 micro.bin 写入到 ROM 中
  2. 手动在 RAM 中写入 MOV A, 5 的机器码
  3. 二地址指令 MOV 对应 ==> 1xxx [aa][bb]
  4. 根据找到的 EXEC = INST[op][am] # 找到IR和寻址方式,拼出 MOV 指令对应 1000 0100,即 84。[aa] = 01 是 AM_REG = 1 # 寄存器寻址,[bb] = 00 是 AM_INS = 0 # 立即寻址 instant
    即 84
  5. A 寄存器是 08
  6. 立即数 5 是 05
  7. pin.DST_W | pin.SRC_OUT,结合CPU 电路图,CPU 控制单元拿到 DST 寄存器的输出 08,通过 CPU 控制单元的 l2 传到 CPU 控制单元内部;拿到 SRC 寄存器的输出 05,通过 CPU 控制单元的 l3 传到 CPU 控制单元内部。最终控制 A 寄存器写入 5。

3.4 实验结果

请添加图片描述

3.5 实验工程

【25 - MOV 指令】

  • 20
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

uuxiang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值