include var.asm ;定义的相关变量的汇编程序
.code
; main 主程序
; 功能描述:每隔一定时间在屏幕上显示一段字符
main proc far ;远过程
mov ax,@code
mov ds,ax ;把程序开始的段地址送到数据段寄存器cli ; 设置前关闭所以中断以防止干扰
call ini_8255 ; 调用初始化8255的子程序
call ini_key2 ; 初始化按键2的子程序
call ini_key1 ; 初始化按键1的子程序
call ini_8253 ; 初始化8253的子程序
call ini_8259 ; 初始化8259的子程序
mov al,20h ; 8259的工作命令字OCW2,表示中断结束为非特殊EOI模式,决定中断请求级别为0
out 20h,al
sti ; 重新打开中断
A2:nop
jmp A2
include ini.asm ;包含进相关8255,8253,8259 的初始化程序,这样才可以调用
include event.asm ;包含进中断相关程序,这样中断才有服务程序
hlt
main endp ;相当于main函数结束
;*********************************
; 按键key2中断程序:IRQ_key2
; 功能描述:相应7号中断(key2),对计数单元完成加一的操作,并为显示作准备
;*********************************
IRQ_key2 proc near
cli push ax push bx push cx push dx push ds
push es push di push si push bp
mov ax,@data ;取得原来的数据段?
mov ds,ax
call EVENT_key2 ;调用按钮key2加1操作
IRQ_key2_exit: ;中断的退出点
mov al,20h out 20h,al pop bp pop si pop di pop es pop ds pop cx
pop bx pop ax
sti ;开中断 iret
IRQ_key2 endp
; 按键key1中断程序:IRQ_key1
; 功能描述:相应7号中断(key1),对计数单元完成减一的操作,并为显示作准备
IRQ_key1 proc near
cli ;关中断 push ax push bx push cx push dx push ds push es push di push si push bp
mov ax,@data ;取得原来的数据段
mov ds,ax
call EVENT_key1 ;调用按钮key1减1操作
IRQ_key1_exit: ;中断的退出点
mov al,20h
out 20h,al pop bp pop si pop di pop es pop ds pop dx pop cx
pop bx pop ax
sti ;开中断 iret
IRQ_key1 endp
; 8253 中断子程序
; 功能描述:8253的定时器0的初始化值为1000,说明计数从1000计到0就产生一次实时时钟中断,计完1000就是1毫秒(1ms),说明机器频率为1M,时钟频率为12M。然而本程序是让8253每产生5次中断才有一次事件处理(数码管某个位显示该数位的值),即数码管的扫描速率是5ms(毫秒)
IRQ_8253 proc near
Cli push ax push bx push cx push dx push ds push es push di
push si push bp
mov ax,@data
mov ds,ax
mov ax,time0_counter ;取得当前的计数器值
cmp ax, TIME0_MAX ;判断是否达到了规定的阀值5毫秒
jl skip_8253 ;小于0转移,如果达到了阀值就清零并调用显示程序,如果没有到达就计数器加1返回
mov time0_counter,0000h ;如果等于5毫秒,即计算结果不小于0则计数器清零
call EVENT_8253 ;调用显示程序
skip_8253: inc time0_counter ;计数器加1
mov al,20h ;中断结束
out 20h,al
pop bp pop si pop di pop es pop ds pop dx pop cx pop b pop ax sti iret
IRQ_8253 endp end
; EVENT_key2子程序-------------------------------------------------------------EVENT 事件
; 功能描述:处理将数据加一的操作(提示:key2按一下才会加1,不按则不加,所以本程序要在按一下中断一次才执行一次的)
EVENT_key2 proc near
;-------------将计数器加1,求得计数器的符号与绝对值,为后面的处理作准备
lea si,data_buffer ;地址传送指令,把data_buffer的有效地址传送到si,si中的值为data_buffer的偏移地址
mov cx,4
;---------------------------------------------- 只执行加1动作
add_loop1:
inc byte ptr ds:[si] ;位数内容加1
cmp byte ptr ds:[si],0ah ;比较指令,ds:[si]操作数减去0ah,结果送到ds:[si]
jne max_test1 ;运算结果不相等转移,ZF=0即要一直加到和10相等
mov byte ptr ds:[si],0 ;如果加到等于10了,si的本位清0
inc si ;转移到高一位位数
dec cx jne add_loop1 ;只能执行四次
;---------------------------------------------- 数位显示的数和数值之间关系的处理的准备
max_test1: mov tep,0000h ;把0000h传到求和的暂时存储器,因为它只是一个数字中转器,所以每次都要清0后再能用
mov cx,4
lea si,data_buffer ;地址传送指令,把data_buffer的有效地址传送到si,si中的值为data_buffer的偏移地址
lea di, mul_times ;把计算的乘数的地址给di
;------- 数位显示的数和数值之间关系的处理,数位显示的数和数值在这里还有本质上区别
max_test_loop1: 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,好让本循环的最后的数可以和MAX_VALUE比较
inc si inc di ;
inc di dec cx
jne max_test_loop1 ;只能执行四次
;---------------------------------------------- 获取和数
get_sum: cmp tep, MAX_VALUE ;和最大值1000比较
jne key2_skip ;不相等转移马上退出
;-------- 若和1000相等,即是最大值了,应该先清0再退出,下面两行是清0之前做的准备
mov cx,4 lea si,data_buffer ;
;---------------------------------------------- 所有显示位清0
clear_loop1: mov byte ptr ds:[si],0;和最大值相等了,每个数位都清0
inc si ;dec cx ;
jne clear_loop1 ;只能执行四次
key2_skip: ret
EVENT_key2 endp
; EVENT_key1子程序
; 功能描述:处理将数据加一的操作(提示:key1按一下才会减1,不按则不减,所以本程序要在按一下中断一次才执行一次的)
EVENT_key1 proc near
;--------------------- 将计数器减1,求得计数器的符号与绝对值,为后面的处理作准备
lea si,data_buffer ;地址传送指令,把data_buffer的有效地址传送到si,si中的值为data_buffer的偏移地址
mov cx,4
;---------------------------------------------- 只执行减1动作
add_loop2: dec byte ptr ds:[si] ;位数内容减1
cmp byte ptr ds:[si],0 ;比较指令,ds:[si]操作数减去0,结果送到ds:[si]
jnl max_test2 ;运算结果不小于转移,SF=0(不小于转移),即要一直减0
mov byte ptr ds:[si],09h ;如果减到小于0了,si的本位置为9
inc si ;转移到高一位位数
dec cx jne add_loop2 ;只能执行四
.code
; main 主程序
; 功能描述:每隔一定时间在屏幕上显示一段字符
main proc far ;远过程
mov ax,@code
mov ds,ax ;把程序开始的段地址送到数据段寄存器cli ; 设置前关闭所以中断以防止干扰
call ini_8255 ; 调用初始化8255的子程序
call ini_key2 ; 初始化按键2的子程序
call ini_key1 ; 初始化按键1的子程序
call ini_8253 ; 初始化8253的子程序
call ini_8259 ; 初始化8259的子程序
mov al,20h ; 8259的工作命令字OCW2,表示中断结束为非特殊EOI模式,决定中断请求级别为0
out 20h,al
sti ; 重新打开中断
A2:nop
jmp A2
include ini.asm ;包含进相关8255,8253,8259 的初始化程序,这样才可以调用
include event.asm ;包含进中断相关程序,这样中断才有服务程序
hlt
main endp ;相当于main函数结束
;*********************************
; 按键key2中断程序:IRQ_key2
; 功能描述:相应7号中断(key2),对计数单元完成加一的操作,并为显示作准备
;*********************************
IRQ_key2 proc near
cli push ax push bx push cx push dx push ds
push es push di push si push bp
mov ax,@data ;取得原来的数据段?
mov ds,ax
call EVENT_key2 ;调用按钮key2加1操作
IRQ_key2_exit: ;中断的退出点
mov al,20h out 20h,al pop bp pop si pop di pop es pop ds pop cx
pop bx pop ax
sti ;开中断 iret
IRQ_key2 endp
; 按键key1中断程序:IRQ_key1
; 功能描述:相应7号中断(key1),对计数单元完成减一的操作,并为显示作准备
IRQ_key1 proc near
cli ;关中断 push ax push bx push cx push dx push ds push es push di push si push bp
mov ax,@data ;取得原来的数据段
mov ds,ax
call EVENT_key1 ;调用按钮key1减1操作
IRQ_key1_exit: ;中断的退出点
mov al,20h
out 20h,al pop bp pop si pop di pop es pop ds pop dx pop cx
pop bx pop ax
sti ;开中断 iret
IRQ_key1 endp
; 8253 中断子程序
; 功能描述:8253的定时器0的初始化值为1000,说明计数从1000计到0就产生一次实时时钟中断,计完1000就是1毫秒(1ms),说明机器频率为1M,时钟频率为12M。然而本程序是让8253每产生5次中断才有一次事件处理(数码管某个位显示该数位的值),即数码管的扫描速率是5ms(毫秒)
IRQ_8253 proc near
Cli push ax push bx push cx push dx push ds push es push di
push si push bp
mov ax,@data
mov ds,ax
mov ax,time0_counter ;取得当前的计数器值
cmp ax, TIME0_MAX ;判断是否达到了规定的阀值5毫秒
jl skip_8253 ;小于0转移,如果达到了阀值就清零并调用显示程序,如果没有到达就计数器加1返回
mov time0_counter,0000h ;如果等于5毫秒,即计算结果不小于0则计数器清零
call EVENT_8253 ;调用显示程序
skip_8253: inc time0_counter ;计数器加1
mov al,20h ;中断结束
out 20h,al
pop bp pop si pop di pop es pop ds pop dx pop cx pop b pop ax sti iret
IRQ_8253 endp end
; EVENT_key2子程序-------------------------------------------------------------EVENT 事件
; 功能描述:处理将数据加一的操作(提示:key2按一下才会加1,不按则不加,所以本程序要在按一下中断一次才执行一次的)
EVENT_key2 proc near
;-------------将计数器加1,求得计数器的符号与绝对值,为后面的处理作准备
lea si,data_buffer ;地址传送指令,把data_buffer的有效地址传送到si,si中的值为data_buffer的偏移地址
mov cx,4
;---------------------------------------------- 只执行加1动作
add_loop1:
inc byte ptr ds:[si] ;位数内容加1
cmp byte ptr ds:[si],0ah ;比较指令,ds:[si]操作数减去0ah,结果送到ds:[si]
jne max_test1 ;运算结果不相等转移,ZF=0即要一直加到和10相等
mov byte ptr ds:[si],0 ;如果加到等于10了,si的本位清0
inc si ;转移到高一位位数
dec cx jne add_loop1 ;只能执行四次
;---------------------------------------------- 数位显示的数和数值之间关系的处理的准备
max_test1: mov tep,0000h ;把0000h传到求和的暂时存储器,因为它只是一个数字中转器,所以每次都要清0后再能用
mov cx,4
lea si,data_buffer ;地址传送指令,把data_buffer的有效地址传送到si,si中的值为data_buffer的偏移地址
lea di, mul_times ;把计算的乘数的地址给di
;------- 数位显示的数和数值之间关系的处理,数位显示的数和数值在这里还有本质上区别
max_test_loop1: 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,好让本循环的最后的数可以和MAX_VALUE比较
inc si inc di ;
inc di dec cx
jne max_test_loop1 ;只能执行四次
;---------------------------------------------- 获取和数
get_sum: cmp tep, MAX_VALUE ;和最大值1000比较
jne key2_skip ;不相等转移马上退出
;-------- 若和1000相等,即是最大值了,应该先清0再退出,下面两行是清0之前做的准备
mov cx,4 lea si,data_buffer ;
;---------------------------------------------- 所有显示位清0
clear_loop1: mov byte ptr ds:[si],0;和最大值相等了,每个数位都清0
inc si ;dec cx ;
jne clear_loop1 ;只能执行四次
key2_skip: ret
EVENT_key2 endp
; EVENT_key1子程序
; 功能描述:处理将数据加一的操作(提示:key1按一下才会减1,不按则不减,所以本程序要在按一下中断一次才执行一次的)
EVENT_key1 proc near
;--------------------- 将计数器减1,求得计数器的符号与绝对值,为后面的处理作准备
lea si,data_buffer ;地址传送指令,把data_buffer的有效地址传送到si,si中的值为data_buffer的偏移地址
mov cx,4
;---------------------------------------------- 只执行减1动作
add_loop2: dec byte ptr ds:[si] ;位数内容减1
cmp byte ptr ds:[si],0 ;比较指令,ds:[si]操作数减去0,结果送到ds:[si]
jnl max_test2 ;运算结果不小于转移,SF=0(不小于转移),即要一直减0
mov byte ptr ds:[si],09h ;如果减到小于0了,si的本位置为9
inc si ;转移到高一位位数
dec cx jne add_loop2 ;只能执行四
离开这里,离开你的视野,归隐到属于我的地方,无论何处