微机接口课设——基于Proteus和8086的打地鼠设计(8255、8253、8259)Proteus中Unknown 1-byte opcode / Unknown 2-byte opcode错误

原理图设计

汇编代码

cpp 复制代码
; I/O 端口地址定义
IOY0 EQU 0600H 
IOY1 EQU 0640H 
IOY2 EQU 0680H

MY8255_A EQU IOY0+00H*2     ; 8255 A 口端口地址
MY8255_B EQU IOY0+01H*2     ; 8255 B 口端口地址
MY8255_C EQU IOY0+02H*2     ; 8255 C 口端口地址
MY8255_MODE EQU IOY0+03H*2  ; 8255 模式控制端口地址

MY8253_COUNT0 EQU IOY1+00H*2 ;8053 计时器0端口地址
MY8253_COUNT1 EQU IOY1+01H*2 ;8053 计时器1端口地址
MY8253_COUNT2 EQU IOY1+02H*2 ;8053 计时器2端口地址
MY8253_MODE EQU IOY1+03H*2 ;8253 模式控制端口地址

MY8259_ODD EQU IOY2
MY8259_EVEN EQU IOY2+01H*2

CODE SEGMENT
    ASSUME CS:CODE, DS:DATA,SS:STACK1


START:
   MOV AX,STACK1
   MOV SS,AX
   
   MOV AX,0000H
   MOV DS,AX
   
   ;写NMI中断(重置)向量表
   MOV AX,OFFSET INTNMI
   MOV SI,02H*4
   MOV [SI],AX
   MOV AX,CS
   MOV [SI+2],AX
   ;写0号中断(慢速)向量表
   MOV AX,OFFSET INT0
   MOV SI,20H*4
   MOV [SI],AX
   MOV AX,CS
   MOV [SI+2],AX
   ;写1号中断(快速)向量表
   MOV AX,OFFSET INT1
   MOV SI,21H*4
   MOV [SI],AX
   MOV AX,CS
   MOV [SI+2],AX
   ;写2号中断(超时)向量表
   MOV AX,OFFSET INT2
   MOV SI,22H*4
   MOV [SI],AX
   MOV AX,CS
   MOV [SI+2],AX
   ;写3号中断(失败)向量表
   MOV AX,OFFSET INT3
   MOV SI,23H*4
   MOV [SI],AX
   MOV AX,CS
   MOV [SI+2],AX
   
   ;这时候再装入数据段,之前让DS段超越是0000(中断向量表特有的要求)
   MOV AX,DATA
   MOV DS, AX   
   
    ;8255工作方式
    MOV AL,90H ;A输入 B输出 C输出
    MOV DX,MY8255_MODE 
    OUT DX,AL
    
    ;8253工作方式 //写在8259前正好ignore掉定时器2因为装载工作字产生的第一次跳变
    MOV DX, MY8253_MODE
    MOV AL, 00110100B ;定时器0,双字节,方式3
    OUT DX, AL
    MOV AL,01111000B ;定时器1,双字节,方式4
    OUT DX,AL
    MOV AL, 10110100B ;定时器2,双字节,方式2
    OUT DX,AL
    
    
    ;8259工作方式
    MOV AL,13H
    MOV DX,MY8259_ODD
    OUT DX,AL
    MOV DX,MY8259_EVEN
    MOV AL,20H
    OUT DX,AL
    MOV AL,01H
    OUT DX,AL
    MOV AL,0E0H
    OUT DX,AL
    
RESET:
   STI
   
   MOV RESETR,0
   MOV SCORER,0
   MOV FAILR,0
   
   ;8255初始化
   ;B全1
    MOV AL,0FFH ;B输出全1
    MOV DX,MY8255_B
    OUT DX,AL
    
    ;PC7(发声器)无效,数码管,老鼠灯全部有效
    MOV AL,00H 
    MOV DX,MY8255_C
    OUT DX,AL
    
    ;8253初始化
    ;计数器1 60秒一次性中断信号
    MOV AX,TIME
    MOV BX,1000
    MUL BX
    MOV DX,MY8253_COUNT1
    OUT DX,AL
    MOV AL,AH
    OUT DX,AL
    
    
    ;计数器2 SPEED秒一次老鼠信号
    MOV AX,SPEED
    MOV BX,1000
    MUL BX 
    MOV DX,MY8253_COUNT2
    OUT DX,AL
    MOV AL,AH
    OUT DX,AL

    ;主工作循环
A0:
   CALL SHOWDATA ;显示数据
   CALL SCAN ;扫描键盘
   CMP ENDR,1
   JE ED
   JMP NED
ED:
   CLI 
   MOV DX,MY8255_C
   MOV AL, 07FH
   OUT DX,AL
   MOV DX,MY8255_B
   MOV AL,00H
   OUT DX,AL
  
   JMP A0
NED:  
   CMP RESETR,1
   JE RESET
   JMP A0

;NMI号中断,处理重置,完成
INTNMI PROC
    CLI
    MOV RESETR,1
    MOV ENDR,0
    STI
    IRET
INTNMI ENDP

; 0号中断,摸鱼模式,完成
INT0 PROC
    CLI
    CMP MODE, 0
    JZ A1
    MOV SPEED, 5
    CALL SETSPEED

    MOV AL,20H
    MOV DX,IOY2
    OUT DX,AL
    STI
A1: 
    IRET 
INT0 ENDP
; 1号中断,鸡血模式,完成
INT1 PROC
   CLI
    CMP MODE, 1
    JZ A2
    MOV SPEED, 2
    CALL SETSPEED ;修改游戏速度
    
    MOV AL,20H
    MOV DX,IOY2
    OUT DX,AL
    STI
A2: 
    IRET
INT1 ENDP

; 2号中断,计时结束,完成
INT2 PROC
    CLI
    MOV ENDR,1
    
    MOV AL,20H
    MOV DX,IOY2
    OUT DX,AL
    STI
    IRET
INT2 ENDP

; 3号中断,老鼠
INT3 PROC
    CLI
    CMP ALIVE, 0
    JZ A3 
    JMP A4
    
    
A3: ;若老鼠死了
   MOV ALIVE,1;死老鼠复活
   
   MOV SOLVE,1
   
   CALL RAND
    MOV AL,20H
    MOV DX,IOY2
    OUT DX,AL
    STI
    IRET
    
A4: ;若老鼠活着
   MOV ALIVE,0;杀死老鼠
   
   XOR AL,AL
   MOV AL,SOLVE
   ADD AL,FAILR
   CMP AL, 2
   JNA A9
   MOV ENDR,1
A9:   
   MOV FAILR,AL
    MOV AL,20H
    MOV DX,IOY2
    OUT DX,AL
    STI
    IRET
INT3 ENDP

; 生成0到5的随机数,并将其转换成老鼠放在RATR中
RAND PROC

    ; 线性同余法参数
    MOV AX, [SEED]       ; 加载当前种子
    MOV BX, 110355      ; 乘数
    IMUL BX              ; AX = AX * BX,结果存储在 DX:AX
    ADD AX, 12345       ; 加增量 c
    MOV BX, 6           ; 限制范围到 0-5
    XOR DX, DX           ; 清空 DX
    DIV BX               ; (DX:AX) / BX,余数在 DX
    MOV SEED, AX       ; 更新种子
    MOV AL, DL ; 保存灯号(余数)
    
    ADD AL,1
    MOV RATR,AL
    
    RET
RAND ENDP


DALLY2 PROC ;防抖延迟
    D0: 
        MOV CX, 8
    D1: 
        MOV AX, 7
    D2: 
        DEC AX
        JNZ D2
        LOOP D1
        DEC DL
        JNZ D0
        RET
DALLY2 ENDP

; 胜利处理过程
WIN PROC
    INC SCORER
    MOV SOLVE, 0

WIN_LODE: ;打开蜂鸣器,加载音乐
    MOV DX,MY8255_C
    MOV AL,11111111B;
    OUT DX,AL
    MOV SI, OFFSET WIN_FREQ_LIST
    MOV DI, OFFSET WIN_TIME_LIST

WIN_PLAY: ;播放音乐
    MOV DX, 0FH
    MOV AX, 4240H
    DIV WORD PTR [SI]
    MOV DX, MY8253_COUNT0
    OUT DX, AL
    MOV AL, AH
    OUT DX, AL
    MOV DL, [DI]
    CALL DALLY3
    ADD SI, 2
    INC DI
    CMP WORD PTR [SI], 0
    JE NOTWIN
    JMP WIN_PLAY

NOTWIN:
    MOV DX,MY8255_C
    MOV AL,01111111B;
    OUT DX,AL
    RET
WIN ENDP


; 失败处理过程
LOSE PROC
    INC FAILR
    MOV SOLVE, 0
    CMP FAILR, 2
    JNA NOTED
    
    MOV ENDR, 1

NOTED:    
LOSE_LODE: ;打开蜂鸣器,加载音乐
    MOV DX,MY8255_C
    MOV AL,11111111B;
    OUT DX,AL
    MOV SI, OFFSET LOSE_FREQ_LIST
    MOV DI, OFFSET LOSE_TIME_LIST

LOSE_PLAY: ;播放音乐
    MOV DX, 0FH
    MOV AX, 4240H
    DIV WORD PTR [SI]
    MOV DX, MY8253_COUNT0
    OUT DX, AL
    MOV AL, AH
    OUT DX, AL
    MOV DL, [DI]
    CALL DALLY3
    ADD SI, 2
    INC DI
    CMP WORD PTR [SI], 0
    JE NOTLOSE
    JMP LOSE_PLAY

NOTLOSE:
    MOV DX,MY8255_C
    MOV AL,01111111B;
    OUT DX,AL
    RET
LOSE ENDP


SETSPEED PROC ;设定游戏速度
    MOV AX, SPEED
    MOV BX,1000
    MUL BX
    MOV DX, MY8253_COUNT2
    OUT DX, AL
    MOV AL,AH
    OUT DX,AL
    RET
SETSPEED ENDP



SHOWDATA PROC ;展示数据到数码管
   CALL PUTBUF
   CALL DISDATA
   RET
SHOWDATA ENDP


DISDATA PROC ;读取缓冲区,数码管显示
   
    MOV SI, 3005H       ; 将SI寄存器指向显示缓冲区起始地址
    MOV CX,6
AGAIN: 
    MOV AL,1
    DEC CL
    ROL AL,CL
    INC CL
    NOT AL
    AND AL,01111111B
    MOV DX, MY8255_C    ;位选
    OUT DX, AL          ; 输出显示码到端口C
    
    MOV AL, [SI]        ; 读取缓冲区中的字符
    MOV BX, OFFSET DTABLE
    AND AX, 00FFH       ; 获取字符的低字节
    ADD BX, AX          ; 计算DTABLE的偏移地址
    MOV AL, [BX]        ; 读取显示码
    MOV DX, MY8255_B
    OUT DX, AL          ; 输出显示码到端口B
    
    CALL DALLY
    DEC SI              ; 移动到下一个缓冲区位置
    LOOP AGAIN           ; 继续输出字符
    
    CMP ALIVE,0
    JE OMIT
    
    MOV AL,00111111B
    MOV DX,MY8255_C
    OUT DX,AL
    MOV AL, RATR        ; 读取老鼠位置
    MOV BX, OFFSET DTABLE
    AND AX, 00FFH       ; 获取字符的低字节
    ADD BX, AX          ; 计算DTABLE的偏移地址
    MOV AL, [BX]        ; 读取显示码
    MOV DX, MY8255_B
    OUT DX, AL          ; 输出显示码到端口B
    CALL DALLY
    
OMIT:    
    RET                 ; 返回
DISDATA ENDP
PUTBUF PROC ;写入缓冲区

    ;读计数器1(游戏时间)计数器值
    ;MOV AL,80H
    ;MOV DX,MY8253_MODE ;锁存
    ;OUT DX,AL
    ;MOV DX,MY8253_COUNT1
    ;IN AL,DX
    ;MOV AH,AL
    ;IN AL,DX
    ;XCHG AH,AL ;读出计数值
    ;XOR DX,DX
    ;MOV BX,1000 
    ;DIV BX ;得到秒数
    
    MOV SI, 3000H
    
    ;MOV BL,10
    ;DIV BL
    ;此时AH是余数个位,AL是十位
    MOV AL,0
    MOV AH,0
    MOV [SI], AL
    MOV [SI+1], AH
    
    
    XOR AH,AH
    MOV AL,SCORER
    MOV BL,10
    DIV BL
    ;此时AH是余数个位,AL是十位
    MOV [SI+2], AL
    MOV [SI+3], AH
    
    XOR AH,AH
    MOV AL,FAILR
    MOV BL,10
    DIV BL
    ;此时AH是余数个位,AL是十位
    MOV [SI+4], AL
    MOV [SI+5], AH
    
    RET
PUTBUF ENDP


DALLY PROC ;显示延迟
    PUSH CX             ; 保存CX寄存器的值
    MOV CX, 8      ; 设置延时计数器
T1: 
    MOV AX, 40       ; 进入内层循环
T2: 
    DEC AX              ; 递减AX
    JNZ T2              ; 如果AX不为零,继续循环
    LOOP T1             ; 每次循环,CX寄存器减1
    POP CX              ; 恢复CX寄存器的值
    RET                 ; 返回
DALLY ENDP
DALLY3 PROC ;音乐延时
    PUSH CX
    PUSH AX
A6:    
    MOV CX,16
A7:
    MOV AX,200
A8:
    DEC AX 
    JNZ A8
    LOOP A7
    DEC DL
    JNZ A6
    POP AX
    POP CX
    RET 
DALLY3 ENDP 
CLEAR PROC
    MOV DX, MY8255_B
    MOV AL, 00H
    OUT DX, AL            ; 清除显示数据
    RET
CLEAR ENDP


SCAN PROC ;扫描按键
   MOV DX,MY8255_A
   IN AL,DX
   NOT AL
   AND AL, 00111111B
   MOV HITR,AL
   CMP HITR, 0
   JZ A5
   CALL DALLY2
   CMP HITR,0
   JZ A5 ;防抖
   JNZ DICIDE
A5:
   RET
SCAN ENDP

DICIDE PROC ;决策函数
    CMP ALIVE,1
    JNE DICIDEL
   ; 将HITR和RATR加载到AL和BL中
    MOV AL, HITR
    MOV BL, RATR
    DEC BL
    ; 将RATR转换成对应的位掩码
    XOR CX, CX      ; 清除CX,用于计数
    MOV CL, BL      ; 将RATR的值移动到CL作为循环计数
    MOV BH, 01H     ; 准备初始掩码00000001b
    
    ROL BH,CL

COMPARE:
    AND AL, BH      ; 比较HITR和转换后的RATR掩码
    JNZ DICIDEW         ; 如果两个值相等,跳转到WIN
    JMP DICIDEL        ; 否则跳转到LOSE
DICIDEW:
   CALL WIN
   RET
DICIDEL:
   CALL LOSE
   RET
DICIDE ENDP

CODE ENDS

STACK1 SEGMENT PARA STACK
	DW 1000H DUP(?)
STACK1 ENDS


DATA SEGMENT
    ; 数据段定义 
    
    ;时间相关
    TIME DW 60      ; 游戏时间设置 60S
    SPEED DW 5 ;老鼠出现时间间隔 5s
    
    ;计数相关
    ;时间计数器由计数器2负责
    SCORER DB 1       ; 打中地鼠的数量计数器
    FAILR DB 2   ; 失败次数计数器
    MODE DB 0 ;游戏模式,0摸鱼模式,1鸡血模式
    
    ;重置相关
    RESETR DB 0 ;重置表示,1重置
    
    ;结束相关
    ENDR DB 0 ;结束表示,1结束
    
    ;音乐相关
    WIN_FREQ_LIST DW 1100, 800,0
    LOSE_FREQ_LIST DW 392, 120,0
    WIN_TIME_LIST DB 1,1
    LOSE_TIME_LIST DB 1,1
    
    ;老鼠存在相关
    ALIVE DB 0;老鼠存在表示,1存在
    
    ;决策相关
    RATR DB 0
    HITR DB 0
    SOLVE DB 0
    
    ;数码管相关
    DTABLE DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH  ; 0~9的显示码
    
    ; LCG 参数
    SEED DW 12345D ; 生成随机数种子
                                
DATA ENDS
END START

Proteus中Unknown 1-byte opcode / Unknown 2-byte opcode错误的可能解决方案

  1. 没用的电路要断开,或者连了外设就要写控制方式字
  2. 数据段要在写完中断向量表之后装载到DS中(这里主要是因为用了DS:SI)
  3. 使用单片8259也要写ICW4
  4. 数据段放在代码段后面
  5. 栈开大一点
  6. 8086内存给够
相关推荐
阿昭L9 小时前
实模式下的地址分段
汇编语言
易享电子4 天前
基于单片机车窗环境监测控制系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
iCxhust5 天前
Proteus8.3打开前期项目版本的方法和步骤
proteus
易享电子6 天前
基于单片机大棚浇水灌溉控制系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
易享电子8 天前
基于单片机智能台灯(调光,时钟)系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
易享电子9 天前
基于单片机电器断路器保护器系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
10岁的博客14 天前
汇编语言:从基础到高级实战指南
汇编语言
逼子格15 天前
【Proteus仿真】虚拟终端出现乱码问题解决
单片机·嵌入式硬件·proteus·嵌入式·硬件工程·电路仿真·虚拟终端
猫头虎1 个月前
2025最新超详细FreeRTOS入门教程:第十三章 FreeRTOS临界区与原子操作
stm32·单片机·嵌入式硬件·物联网·51单片机·proteus·iot
小莞尔1 个月前
【51单片机】【protues仿真】基于51单片机公交报站系统
stm32·单片机·嵌入式硬件·51单片机·proteus