📄 code.asm
字号:
;路口定义:1路口为东,2路口为南,3路口为西,4路口为北
CODE SEGMENT
ASSUME CS:CODE
INTPORT1 EQU 0020H ;定义8259的控制口地址,用来写ICW1
INTPORT2 EQU 0021H ;定义8259的数据口地址,用来写ICW2,3,4
INTQ3 EQU INTERUPT3 ;定义3号中断向量对应的处理函数
INTQ7 EQU INTERUPT7 ;定义7号中断向量对应的处理函数
CONTPORT EQU 00DFH ;8255的控制口地址
DATAPORT EQU 00DEH ;8255的数据口地址
CtrPort EQU 0073H ;8255的方式选择控制字地址
APort EQU 0070H ;8255的A口地址,A口在本实验中未使用
BPort EQU 0071H ;8255的B口地址,PB4-PB7控制四个路口直行灯的亮灭(本例为PB0-PB3)
CPort EQU 0072H ;8255的C口地址,PC0-PC3控制四个路口左转灯,PC4-PC7控制右转灯,0为亮,1为灭??
DATA1 EQU 0500H ;电平错误显示区首地址,INTQ7显示错误时使用
DATA2 EQU 0508H ;在CONVERS1中使用到 ,为显示字符区首地址
DATA4 EQU 0520H ;显示缓冲区的首地址
DATA5 EQU 0528H ;LEDDISP中使用,保存显示到第几位
DATA6 EQU 0529H ; INTERUPT3 中使用,用于保存8259收到8253时钟脉冲的次数
DATA7 EQU 052AH ;保存当前四个路口的灯处于哪个状态(共4个)
DATA8 EQU 052BH ;保存剩余的秒数,在FORMAT函数的最后进行初始定义
DATA9 EQU 052CH ;保存剩余的秒数,在FORMAT函数的最后进行初始定义
DATA10 EQU 052EH ;在CONVERS2中使用,作为指针,指向显示缓冲区的某一位
ORG 1800H ;存储地址的偏移量
START:
;------------------------ 初始化存储空间和各个芯片--------------------------------
CALL FORMAT
CLD
;初始化8253
MOV DX,004BH
MOV AL,0B6H
OUT DX,AL
MOV DX,004AH
MOV AL,50H
OUT DX,AL
MOV AL,0C3H
OUT DX,AL
; 定义8255的工作方式,三个端口均工作于方式0,均为输出口
MOV AL,80H
MOV DX,CtrPort
OUT DX,AL
;写中断向量
MOV AX,0H
MOV DS,AX
CALL writeINT
MOV AL,13H ;初始化8259
MOV DX,INTPORT1
OUT DX,AL
MOV AL,08H
MOV DX,INTPORT2
OUT DX,AL
MOV AL,0BH
OUT DX,AL
MOV AL,0F7H
OUT DX,AL
;--------------------------------------------------------------------------------
;---------------------等待模块,用来调用中断服务程序和交通灯状态程序------------------
WATING: STI ;开中断
CMP BYTE PTR DS:[DATA7],01H ;判断是否为状态一
JA WATING1 ;如果不是则转WATING1
CMP BYTE PTR DS:[DATA8],03H ;如果是状态一,看当前时间剩余值是否大于3
JNA ZT1F ;如果小于等于3秒,则调用状态一闪烁程序
CALL ZT1 ;如果大于3秒,则调用状态一程序
JMP WATING
WATING1: CMP BYTE PTR DS:[DATA7],02H
JA WATING2
CMP BYTE PTR DS:[DATA8],03H
JNA ZT2F
CALL ZT2
JMP WATING
WATING2: CMP BYTE PTR DS:[DATA7],03H
JA WATING3
CMP BYTE PTR DS:[DATA8],03H
JNA ZT3F
CALL ZT3
JMP WATING
WATING3: JMP WATING4 ;跳转到WATING4,因为JNA指令只能在段内跳转范围为-127b-128b,
;-------------------------------------------------------------------------------------
;-----------------------------交通灯状态子程序-----------------------------------------
;-------------状态1: 2、4路口直行灯点亮------------------
ZT1: PUSH AX
PUSH DX
MOV AL,01010000B ;设置2,4路口直行灯亮
MOV DX,BPort ;BPort为8255A的PB口的地址
OUT DX,AL ;更改PB口的值,从而改变LED灯显示的状态
MOV AL,00H ;设置四个路口左转灯,右转灯全部关闭
MOV DX,CPort ;CPort为8255A的PC口的地址
OUT DX,AL ;更改PC口的值,从而改变LED灯显示的状态
POP DX
POP AX
RET
ZT1F: ;状态一闪烁程序: 2、4路口直行灯闪烁
PUSH AX
PUSH DX
MOV CX,12H ;定义闪烁12次
ZT1Flash:MOV AL,00H ;灯灭
MOV DX,BPort
OUT DX,AL
CALL DELAY2 ;短延时
MOV DX,BPort
MOV AL,01010000B ;灯亮
OUT DX,AL
CALL DELAY2 ;短延时
LOOP ZT1Flash ;循环
POP DX
POP AX
JMP WATING
;-----------------------------------------------------------------
;---------------状态2: 1、3路口左转灯亮,2、4路口右转灯亮---------
;------------------------------------------------------------
;------------------------------交通灯闪烁延时程序------------
DELY2: CALL DELAY2
LOOP DELY2
POP CX
POP AX
RET
DELAY2: PUSH CX
MOV CX,9000H
DELA1: LOOP DELA1
POP CX
RET
;---------------------------------------------------------------------------------------
writeINT: MOV AX,0H ;写中断向量子程序
MOV ES,AX
MOV DI,002CH
LEA AX,INTQ3
STOSW
MOV AX,CS
STOSW
MOV DI,003CH
LEA AX,INTQ7
STOSW
MOV AX,CS
STOSW
RET
;----------------------------------------------中断处理程序-----------------------------------
INTERUPT3:
CLI ;处理中断时先关中断
PUSH AX
PUSH DX
MOV AL,DS:[DATA6] ;DATA6 EQU 0529H 地址中为00D ,用于保存收到的中断次数
INC AL
MOV DS:[DATA6],AL ;将00D改为 01D ,DATA6用于保持收到脉冲的次数,满20时加1
CMP AL,20H
JAE NEXT ; 大于等于20时,清零,并转向状态判断程序,中断返回
JMP INTRE2 ;小于时中断返回
NEXT: MOV BYTE PTR DS:[DATA6],00H ;将中断计数器清零
CALL LEDDISP ;将显示缓冲区中的数字显示出来
CALL NEWTIME ;将时间缓冲区中的数字减一
P1: CMP BYTE PTR DS:[DATA7],01H ;判断是否是第一个状态
JNZ P2 ;如果不是第一个状态,则转P2
CMP BYTE PTR DS:[DATA8],00H ;看20S是否已经减到0
JNE CONV ;如果未减到0,则更新显示缓冲区,并中断返回
MOV BYTE PTR DS:[DATA7],02H ;如果减到0,则转到第二个状态
MOV BYTE PTR DS:[DATA9],8H ; 设定2状态时,路口的显示初始值
MOV BYTE PTR DS:[DATA8],8H ;
JMP CONV
CONV: CALL CONVERS ;把时间缓冲区中的时间转换到显示缓冲区中
INTRE2: CALL LEDDISP
MOV AL,20H ;写8259控制口 ,并中断返回
MOV DX,INTPORT1
OUT DX,AL
POP DX
POP AX
STI ;开中断
IRET ;中断返回
;------------------------------------------------------------------------------------------------
INTERUPT7: CLI ;电平不符合要求时,自动显示ERR
MOV SI,DATA1
CALL LEDDISP
MOV AL,14H
MOV DX,INTPORT1
OUT DX,AL
IRET
;-----------------------------转换子程序,将时间数值转换为显示字符,存入显示缓冲区-----------------
CONVERS: MOV AL,BYTE PTR DS:[DATA9] ;转换2,4路口(对应于实验仪上右边显示屏)的秒
CALL CONVERS2
ADD WORD PTR DS:[DATA10],03H ;转换1,3路口(对应于实验仪上左边显示屏)的秒
MOV AL,BYTE PTR DS:[DATA8]
CALL CONVERS2
MOV WORD PTR DS:[DATA10],DATA4 ;恢复[DATA10]的指向显示缓冲区首地址
RET
CONVERS2: PUSH AX
CALL CONVERS1 ;转换低位
MOV BX,WORD PTR DS:[DATA10]
MOV DS:[BX],AL ;更新低位所对应的显示缓冲区
ADD WORD PTR DS:[DATA10],01H ;[DATA10]指向高位
POP AX
PUSH CX
MOV CL,4H
SHR AL,CL ;AL右移CL(4)位, 丢弃低4位,如AL为12H,则转换为01H
POP CX
CALL CONVERS1 ;转换高位
MOV BX,WORD PTR DS:[DATA10] ;更新高位所对应的显示缓冲区
MOV DS:[BX],AL
RET
CONVERS1: MOV BH,0H
AND AL,0FH ;取AL的低位 ,如AL为12H,则取02H
MOV BL,AL ; 将数值存入BL中,作为基址
MOV AL,CS:[BX+DATA2] ;将相应的显示字符存入AL,如将2对应的字符存入AL.
RET
;-------------------------------------------------------------------------------------------
;--------------------------------更新时间缓冲区子程序---------------------------------------
NEWTIME:
MOV AL,BYTE PTR DS:[DATA9] ;[DATA789]全部加1D
SUB AL,01D
DAS ;减法的十进制调整,如12D改为12H
MOV BYTE PTR DS:[DATA9],AL
MOV AL,BYTE PTR DS:[DATA8]
SUB AL,01D
DAS
MOV BYTE PTR DS:[DATA8],AL
RET ;返回
;----------------------------------------------------------------------------------------------
;-------------------------------------显示子程序,调用时显示时间缓冲区中的字符--------------------------
LEDDISP:
PUSH AX ;显示子程序
PUSH BX
PUSH CX
PUSH DX
MOV SI,DATA4 ;DATA4 EQU 0520H 从0520h开始显示
MOV AL,90H ;初始显示时 DATA3 EQU 0518H
MOV DX,CONTPORT ;写8255控制口
OUT DX,AL
MOV BYTE PTR DS:[DATA5],00H ;DATA5 EQU 0528H
LED1: CMP BYTE PTR DS:[DATA5],05H
JA LED2 ;如果显示完8位后,返回
MOV BL,DS:[DATA5]
MOV BH,0H
MOV AL,CS:[BX+SI] ; 初始时,SI等于DATA3 0518H ,
;INTQ3时等于DATA4 0520H ,从0520h显示到0527H
MOV DX,DATAPORT ;写8255数据口,以此改变显示值
OUT DX,AL
ADD BYTE PTR DS:[DATA5],01H ;显示下一位
JNZ LED1
LED2:
POP DX
POP CX
POP BX
POP AX
RET
;---------------------------------------------------------------------------------------------------------
FORMAT: MOV BX,0 ;DATA1 EQU 0500H
MOV WORD PTR DS:[BX+DATA1],5050H ; 1 0 INTQ7中使用,显示ERR
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],0079H ;3 2
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],0000H ;5 4
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],0000H ;7 6
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],063FH ;9 8 显示字符 1 0
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],4F5BH ;0B 0A 3 2
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],6D66H ;0D 0C
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],077DH ;0F 0E
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],6F7FH ;11 10
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],7C77H ;13 12
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],5E39H ;15 14
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],7179H ;17 16
;----------------------------------------- 初始化时显示 ------------------------
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],663FH ;19 18 40
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],3F3fH ;1B 1A 0-
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],3F3FH ;1D 1C 00
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],3F3FH ;1F 1E 00
ADD BX,2
;-------------------------------------------------------------------------------
;-------------显示缓冲区,保存着当前时间对应的显示字符,INTQ3中进行调用和修改-----------
MOV WORD PTR DS:[BX+DATA1],065bH ;21 20 初次显示12
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],0000H ; 23 22 0-
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],065bH ;25 24 初次显示12
ADD BX,2
MOV WORD PTR DS:[BX+DATA1],0000H ; 27 26 00
;---------------------------------------------------------------------------------------
MOV BYTE PTR DS:[DATA6],00H ;保存8259A当前收到时钟脉冲的次数
MOV BYTE PTR DS:[DATA7],01H ;设置初始状态
MOV BYTE PTR DS:[DATA8],12H ;设置刚开始正常工作后1,3路口显示的秒数
MOV BYTE PTR DS:[DATA9],12H ;设置刚开始正常工作后2,4路口显示的秒数
MOV WORD PTR DS:[DATA10],DATA4
RET
;--------------------------------------------------------------------------------------------
CODE ENDS
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -