第一章课程设计一
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第一章课程设计一
一、设计题目
要求编制实现以下功能的中断程序:在主程序运行期间,每5秒钟响铃一次;当键盘上的某个键被按下时,主程序和响铃都被挂起,显示器显示buffer缓冲区中的字符串,然后等待下一次按键引起的键盘中断;当键盘中断发生后,恢复主程序和响铃.这一过程可以重复任意次。
二、设计思路
(1)本设计需要定时器及键盘两个中断源,这两个中断源的关系是:在主程序运行期间(可用loop指令作空闲循环来模拟),cpu既能响应定时器每秒18.2次的中断请求,也能响应键盘的中断请求。当第一次按键产生中断后,应禁止定时器的中断,并开始显示字符串。只有第二次按键产生中断时,才恢复定时器的中断并返回主程序。
(2)主程序中应分别保存定时器及键盘的原中断向量,设置自编处理程序的中断向量,清除定时器和键盘的中断屏蔽位并开中断。在返回DOS之前,恢复定时器和键盘原来的中断向量。
(3)按下键和放开键都能引起键盘中断,但在处理键盘中断时,对按键所产生的代码不必解释处理,只需根据读取的扫描码的最高位确定是按键中断还是释放键中断。如果是释放键引起的中断,则无须做任何工作,直接从中断处理程序中退出。如果是按下键引起的中断,则要区别是第一次按键还是第二次按键,以便作出不同的处理,为此可设置一个标志变量flag。
(4)每次按下键产生的中断,使flag的最低位发生一次变化,设flag的初始值为0,则第一次按键使其变为1,第二次按键使其变为0...,这样通过判断flag为1或0来区别两次按键,并分别转入不同的处理。
(5)第一次按键的处理功能是屏蔽定时器中断,使之不再控制响铃,然后等待第二次键盘中断,为此必须清除第一次按键产生的中断级。
三、程序说明
1、程序名称:inter
2、程序功能:该程序实现:在主程序运行期间,每5秒钟响铃一次;当键盘上的某
个键被按下时,主程序和响铃都被挂起,显示器显示buffer缓冲区中
的字符串,然后等待下一次按键引起的键盘中断;当键盘中断发生
后,恢复主程序和响铃.这一过程可以重复任意次。
3、寄存器使用情况:
在main函数部分:DX 用于存放自编中断例行程序偏移地址
AX 用于存放子程序入口地址的段基址
DI 、SI 用作产生延迟时间的计数值
AL 、AH在取或设置中断向量功能调用时保存调用参数
AL 用于I/O指令中
在程序timer部分:DL用于2号功能调用时保存调用参数
在程序kbdint部分:AL 用于I/O指令中
4、流程图
N
图1 程序inter的流程图
四、程序清单
data segment ;定义数据段开始
keep_ip08 dw ? ;定义存储单元保存原中断向量
keep_cs08 dw ?
keep_ip09 dw ?
keep_cs09 dw ?
flag db 0 ;定义变量flag判flag为1或0来区别两次按键count dw 1 ;定义变量count初值为1
mess db 0ah,0dh,'Bell!',0ah,0dh,'$';定义2个字符串
buffer db 0ah,0dh,'Keyboard Interrupt!',0ah,0dh,'$'
data ends ;数据段定义结束
stack segment para stack 'stack';定义堆栈段开始
dw 100 dup(0) ;堆栈大小为100个字
stack ends ;堆栈段定义结束
code segment ;定义代码段开始
assume cs:code,ss:stack,ds:data
main proc far ;定义过程开始
start: ;START为程序执行时的启始标号
mov ax,data
mov ds,ax
mov al,1ch ;取类型号为1CH的原中断向量
mov ah,35h ;取中断向量的功能调用
int 21h ;段址放入ES,偏址放入BX
mov keep_ip08,es ;保存旧向量,存原中断向量段址
mov keep_cs08,bx ;存原中断向量偏移量
push ds ;保存DS
lea dx,timer ;子程序入口地址的偏移量(自编中断例行程序偏移地址)送DX mov ax,seg timer ;子程序入口地址的段基
mov ds,ax ;中断向量送DS,自编中断例行程序段地址放入DS
mov al,1ch ;设置新中断向量1c(定时器中断),中断类型放入AL mov ah,25h ;设置中断向量的功能调用
int 21h ;设置新的中断向量,改变中断向量
pop ds ;恢复DS
mov al,09h ;取中断向量09h
mov ah,35h
int 21h
mov keep_ip09,es ;保存旧向量,存原中断向量段址
mov keep_cs09,bx ;存原中断向量偏移量
push ds
lea dx,kbdint ;新偏移量送DX,设置新中断向量09h(键盘中断) mov ax,seg kbdint
mov ds,ax ;新段址送DS,中断向量送DS
mov al,09h ;写入新的中断向量
mov ah,25h
int 21h
pop ds
in al,21h ;设置中断屏蔽寄存器,重新增设键盘中断和定时器中断
and al,0fch ;键盘和定时器址直由第0和1位
out 21h,al
sti ;开中断,设置中断允许位(IF=1),允许CPU响应外设中断请求mov di,20000 ;其实就是一个延时
dly: mov si,30000 ;延时
dly1: dec si ;以下是一个双循环,就是控制程序时间jnz dly1
dec di ;可以调整si,di的数值,如果大,就是显示时间长
jnz dly ;主程序工作(期间每秒产生中断18.2次)
cli ;清除中断允许位(IF=0),禁止CPU响应任何外设中断jmp start
push ds ;保存DS
mov dx,keep_ip08 ;恢复中断向量1ch
mov ax,keep_cs08
mov ds,ax ;自编中断例行程序段地址放入DS
mov al,1ch ;中断类型
mov ah,25h ;设置中断向量
int 21h ;DOS调用
pop ds ;恢复DS
push ds ;保存DS
mov dx,keep_ip09 ;恢复中断向量09h(键盘中断),取出保存的偏移地址mov ax,keep_cs09 ;取出保存的段地址
mov ds,ax
mov al,09h ;中断类型
mov ah,25h ;设置中断向量
int 21h ;DOS调用
pop ds ;恢复DS
mov ah,4ch ;结束程序
int 21h
main endp
;------------------------------------------------------------------------------- timer proc near
push ds
push ax
push cx
push dx ;保存所有已修改的寄存器
mov ax,data
mov ds,ax ;数据段段始址送DS
dec count ;给count减1,就是变成0
jnz exit ;不等于0退出,其实等于,所以输出