;---------------------------------------------- 数位显示的数和数值之间关系的处理的准备
max_test2: mov tep,0000h ;把0000h传到求和的暂时存储器,因为它只是一个数字中转器,所以每次都要清0后再能用
mov cx,4 lea si,data_buffer lea di, mul_times ;把计算的乘数的地址给di
;-- 数位显示的数和数值之间关系的处理,数位显示的数和数值在这里还有本质上区别
max_test_loop2: mov ah,0 ;
mov al,byte ptr ds:[si];
mov bx, ds:[di] ;乘数
mul bx ;al乘以bx,结果送到ax(和dx)
add ax,tep ;把相乘结果和和暂时存储器tep相加结果送到ax
mov tep,ax ;再把ax结果送到tep,好让本循环的最后的数可以和最大值比较
inc si ;增加到高一位的显示数据地址
inc di inc di ;因为乘数在变量定义文件var.asm中是字增加到高一位乘数
dec cx
jne max_test_loop2 ;只能执行四次
;---------------------------------------------- 获取差数
get_margin: cmp tep, MIN_VALUE ;和最小值0比较
jne key1_skip ;不相等转移马上退出
;- 和0相等,即是最小值了,应该将其置为1000再退出,下面两行为置为1000做的准备
mov cx,3
lea si,data_buffer
;---------------------------------------------- 置为1000
clear_loop2: mov byte ptr ds:[si],0;和最小值相等了,为了置为1000,前三个为0
inc si ;dec cx ;
jne clear_loop2 ;只能执行三次
mov byte ptr ds:[si],1 ;第4个置为1才能成为1000
key1_skip: ret
EVENT_key1 endp
; EVENT_8253子程序
; 功能描述:CPU把各位数转化为数码管的7段显示规则码发送到8255的IO端口,然后通过IO端口连接到数码管来显示
EVENT_8253 proc near
mov bp,show_number ;显示的控制字,PA口用
lea si,data_buffer 把data_buffer的有效地址传送到si,si中的值为data_buffer的偏移地址
mov al,byte ptr ds:[si+bp];数码管各数位的值
mov ah,0
mov bp,ax ;把各位的数送到bp
lea si,number_led
mov al,byte ptr ds:[si+bp];把数字对应的字型码传送给al
out PB,al ;把字型码al直接传到8255的PB口,PB口接的数码管的字型线,控制数码管的字型,控制哪一位上的字形
mov cx,show_number ;控制字传到待移位寄存器的移位数寄存器里
mov ax,0001h
rol ax,cl ;左循环移位,一次移动cl位,
inc show_number ;自增1,轮到左边数码管显示
cmp show_number,0004h ;和4相等相当于要到第五个管,这里没有第五个管,所以下面清0
jne not_reach_head ;不相等转移
mov show_number,0 ;4个管都显示了,回到第一个管的位线控制字值
not_reach_head: not al ;取反让其位线值为0就显示
out PA,al ;输出到8255的PA口,PA口接的数码管的字位线控制数码管的字位 PA控制哪一位亮
ret ;返回
EVENT_8253 endp
; ini_8259 初始化8259子程序---------------------------------------------------------INT部分
ini_8259 proc near ;近过程
in al,21h
and al,OPEN_INT0 ;开启中断0
out 21h,al ;CPU把控制信号输出到21端口
in al,21h and al,OPEN_INT7 ;开启中断7
out 21h,al in al,21h
and al,OPEN_INT6 ;开启中断6
out 21h,al ret
ini_8259 endp
;*********************************
; ini_8253 子程序
ini_8253 proc near
mov ax,0 ;设置附加段到中断向量表,设置中断向量表的段地址为0000h
mov es,ax
;------------- 修改8253中断向量偏移地址
mov di,INT0_VECTOR_OFFSET ; 获得8253(即8259中断0)在中断向量表的偏移地址的指针
mov ax, offset IRQ_8253 ;获得8253(即8259中断0)中断程序的偏移地址
mov es:[di],ax ;将8253(即8259中断0)中断向量的偏移地址指向自定义8253中断程序(IRQ_8253)
;------------- 修改8253中断向量段地址
mov di,INT0_VECTOR_SEGMENT ;获得8253(即8259中断0)在中断向量表的段地址的指针
mov ax, @code 获得8253(即8259中断0)中断程序的段地址
mov es:[di],ax ;将8253(即8259中断0)中断向量的段地址指向自定义8253中断程序(IRQ_8253)
;----------------------------- 定时器0赋初值,即初始化
mov al,TIME_SEL_0 ;写控制字到8253控制寄存器,选择0号通道
out TCTR ,al mov al,TIME0_LOW ;低位数据(0e8h)到定时器0寄存器
out T0,al
mov al,TIME0_HIGH ;写高位数据(03h)到定时器0的数据寄存器
out T0,al ret
ini_8253 endp
;********************************
; ini_key2 子程序;********************************
ini_key2 proc near
mov ax,PRGRAM_SEGMENT mov es,ax ;--------------- 修改中断向量,将中断程序指向自定义中断程序,key2的接口
mov ax, offset IRQ_key2 ;取得key2中断(8259中断7)程序入口偏移地址
mov di, INT7_VECTOR_OFFSET ;取得(8259中断7)中断向量表中的偏移地址指针
mov es:[di],ax ;替换偏移地址
mov ax,@code ;获得(8259中断7)程序的段地址
mov di,INT7_VECTOR_SEGMENT ;取得(8259中断7)中断向量表中的段地址指针
mov es:[di],ax ;替换段地址
ini_key2 endp
;********************************
; ini_key1 子程序;********************************
ini_key1 proc near
mov ax,PRGRAM_SEGMENT
mov es,ax ;- 修改中断向量,将中断程序指向自定义中断程序,key1的接口
mov ax, offset IRQ_key1 ;取得key1中断(8259中断6)程序入口偏移地址
mov di, INT6_VECTOR_OFFSET ;取得(8259中断6)中断向量表中的偏移地址指针
mov es:[di],ax ;替换偏移地址
mov ax,@code ;获得(8259中断6)程序的段地址
mov di,INT6_VECTOR_SEGMENT ;取得(8259中断6)中断向量表中的段地址指针
mov es:[di],ax ;替换段地址
ini_key1 endp
;*********************************
; ini_8255 子程序;*********************************
ini_8255 proc near
;-------------- 开始设置工作
mov al,CTR_SHOWONLY ;设置8255控制字
out PCTR,al mov al,0ffh
out PB,al ; 将字线全部开启
mov al,0 out PA,al ; 将位线开启
ret
ini_8255 endp
;**********************************--------------------------------------------VAR部分
; 常量定义
PRGRAM_OFFSET equ 2000H ;程序开始的偏移地址
PRGRAM_SEGMENT equ 0000H ;程序开始的段地址
INT7_VECTOR_OFFSET equ 003cH ;8259中断7在中断向量表中的偏移地址,用作Key2的中断触发
INT7_VECTOR_SEGMENT equ 003eH ;8259中断7在中断向量表中的段地址 , 用作Key2的中断触发
INT6_VECTOR_OFFSET equ 0038H ;8259中断6在中断向量表中的偏移地址,用作Key1的中断触发
INT6_VECTOR_SEGMENT equ 003aH ;8259中断6在中断向量表中的段地址 , 用作Key1的中断触发
INT0_VECTOR_OFFSET equ 0020H ;8259中断0在中断向量表中的偏移地址, 用作8253的0号通道中断
INT0_VECTOR_SEGMENT equ 0022H ;8259中断0在中断向量表中的段地址, 用作8253的0号通道中断
;****** 8259端口控制定义字,8259的工作命令字OCW1(中断屏蔽命令字)
MSAK_INT7 equ 10000000B ;8259中断屏蔽中断7用的字
OPEN_INT7 equ 01111111B ;8259中断开启中断7用的字
MSAK_INT0 equ 00000001B ;8259中断屏蔽中断0用的字
OPEN_INT0 equ 11111110B ;8259中断开启中断0用的字
MSAK_INT6 equ 01000000B ;8259中断屏蔽中断6用的字
OPEN_INT6 equ 10111111B ;8259中断开启中断6用的字
;*************************** 8255常量定义端口地址
PA equ 60h ;8255A口的I/O地址
PB equ 61h ;8255B口的I/O地址
PC equ 62h ;8255C口的I/O地址
PCTR equ 63h ;8255的控制I/O地址
;************************* 8255端口控制定义字
CTR_SHOWONLY equ 10000000B ;A口与B口都工作在方式0,C口全部输出, A口输出控制位线,B口输出控制字形,C口不使用
;*************************** 8253常量定义端口地址
T0 equ 40h ;8253定时器0号端口地址
T1 equ 41h ;8253定时器1号端口地址
T2 equ 42h ;8253定时器2号端口地址
TCTR equ 43h ;8253的控制端口地址
;************************* 8253端口控制定义字
TIME_SEL_0 equ 00111100B ;选择端口0,先控制低位,再控制高位,工作方式为2(方式2可作为一个脉冲速率发生器或用于产生实时时钟中断,本程序就是用来产生实时时钟中断),数据格式是二进制
TIME0_LOW equ 0e8h ;定时器0的数据的高位和低位,设置为1000,说明计数从1000计到0就产生实时时钟中断,计完1000,1毫秒(1ms),说明机器频率为1M,时钟频率为12M
TIME0_HIGH equ 03h
TIME0_MAX equ 5 ;定时器0计数的最大值
;************************** 定义的程序用常量
MAX_VALUE equ 1000 ;定义显示的最大值
MIN_VALUE equ 0 ;定义显示的最小值
; 变量量定义
time0_counter dw 0000h ;定时器0的计数器的值,每个单位代表一个毫秒,当大于阀制后清零
number_led db 03fh,06h,05bh,04fh,66h,06dh,07dh,07h,07fh,06fh ;显示的0--9的字型码
data_buffer db 00h,00h,00h,00h ;代表显示的数字共四位
show_number dw 0000h ;显示的控制字,PA口用
mul_times dw 1,10,100,1000 ;计算的乘数
tep dw 00 ;求和的暂时存储器