北京邮电大学微机原理软件实验·第三次实验题目一:一、实验目的1、初步掌握中断程序的设计方法;2、初步掌握修改DOS 系统中断,以适应实际使用的方法。
二、实验内容编一程序,在显示器上显示时、分、秒。
借用计数器8253的Timer0作为中断源,通过8259A向CPU发中断,每10ms产生一次中断。
在中断服务程序中管理刷新时、分、秒。
要求:1、输入文件名(如:CLK)后清屏后显示:2、Current time is: xx:xx:xx(时分秒键盘输入)3、打回车,时、分、秒开始计时。
时钟不停的刷新。
4、当键入CTRL+C时,停止计时,返回系统,且系统正常运行不死机。
提示:8253的初始化程序段可借用。
口地址为40H、41H、42H、43H,控制字为36H=00110110B,时间常数TC=11932:1.1932MHz/11932=100Hz,输出方波频率为100Hz,其周期为1000/100=10ms。
三、设计思路1、程序流程图开始定义数据段和堆栈段保存源中断向量将timer子程序地址设置为中断向量设置8253工作状态,使其输出方波100Hz设置8259A工作状态输出一条提示信息,要求用户设定时间判断设定时间是否符合规范否输出一条错误信息是显示字符串:“Nowthe time is:”判断内存中的时间是否被修改是重新在屏幕上打印时间否判断键盘缓冲区有无按键按下回车是否按下是秒表功能否判断“S”是否按下是否判断Ctrl+C是否按下是退出程序否2、中断子程序流程图子程序开始记下进入中断的次数判断次数是否为100是计数清零,修改内存中存储的时间查看是否否有进位进位调整结束3、可能用到的指令①STI 置中断允许位.CLI 清中断允许位.格式:CLI STI功能:开关中断允许标志,用于在程序中防止中断嵌套,设置中断。
②STOS(STOre into String) 存入串指令格式:STOS DSTSTOSB //存放字节串( DI ) = ALSTOSW //存放字串( DI ) = AX执行操作:把AL或AX中的内容存放由DI指定的附加段的字节或字单元中,并根据DF值修改及数据类型修改DI的内容。
字节操作:((DT))←(AL),(DI)←(DI)±1字操作:((DI))←(AX),(DI)←(DI)±2无条件转移指令③IN输入指令长格式为:IN AL,PORT(字节)IN AX,PORT(字)执行的操作:(AL)<-(PORT)(字节)(AX)<-(wPORT+1,PORT)(字)短格式为:IN AL,DX(字节)IN AX,DX(字)④OUT输出指令长格式为:OUT PORT,AL(字节)OUT PORT,AX(字)执行的操作:(PORT)<-(AL)(字节)(PORT+1,PORT)<-(AX)(字)短格式为:OUT DX,AL(字节)OUT DX,AX(字)执行的操作:((DX))<-(AL)(字节)((DX)+1,(DX))<-AX(字)⑤设置中断向量格式:mov al,8mov ah,25hint 21hDS:DX=中断向量AL=中断类型号⑥查看中断向量格式:mov al,8mov ah,35hAL=中断类型ES:BX=中断向量4、计数器芯片8253简介①初始化使用8253前,要进行初始化编程。
初始化编程的步骤是:A向控制寄存器端口写入控制字对使用的计数器规定其使用方式等。
B 向使用的计数器端口写入计数初值。
②8253控制字D7D6=00:使用0号计数器,D7D6=01:使用1号计数器D7D6=10:使用2号计数器,D7D6=11:无效D5D4=00:锁存当前计数值D5D4=01:只写低8位(高8位为0),读出时只读低8位D5D4=10:只写高8位(低8位为0),读出时只读高8位D5D4=11:先读/写低8位,后读/写高8位计数值D3D2D1=000:选择方式0,D3D2D1=001:选择方式1D3D2D1=X10:选择方式2,D3D2D1=X11:选择方式3D3D2D1=100:选择方式4,D3D2D1=101:选择方式5D0=0:计数初值为二进制,D0=1:计数初值为BCD码数四、源程序data segmentcount100 db 100;100个10ms=1s,此处count100起计数作用msg1 db 'Please enter the currenttime(XX:XX:XX)!(Press ENTER to use default time)$' msg2 db 'Sorry,your date enteredincorrectly ,please try again!$'msg3 db 'Now, the time is:',0ah,'(Press Ctrl+C to EXIT.)',0ah,'(Press Enter to use as a Stopwatch.)',0ah,'(Press S or s to set current time again.)(XX:XX:XX)$'msg4 db 0ah,'Program EXIT normally.$'tenhour db '0';小时十位数hour db '0',':';小时个位数tenmin db '0';分钟十位数minute db '0',':' ;分钟个位数tensec db '0';秒十位数second db '0’;秒个位数data endsstack segment stack 'stack'db 256 dup(0)stack endscode segmentassume cs:code,ds:data,es:datastart: mov ax,seg datamov es,axmov ds,axcli ;使中断标志IF=0mov al,8;保存源中断向量mov ah,35hint 21hpush espush bx mov ax,0mov es,ax; es置零,这是准备中断向量的写入mov di,20hmov ax,offset timer;中断子程序timer的偏移量stows;字符串填充,将AX的内容;(timer偏移量)存入di所指向的单元,;di的增减取决于DF,默认段基址总是ES mov ax,csstosw;timer端基址mov al,36hout 43h,a;设置8253控制字为36Hmov bx,11932;分频系数为11932,分频结;果1.1932MHz/11932=100Hz,10ms变化一次mov al,bl;分两次设置分频系数out 40h,almov al,bhout 40h,almov al,0fch;主PIC端口设置为0fchout 21h,alsti;开中断,允许外部中断mov ax,seg datamov es,axmov ds,axmov dx,offset msg1;打印提示信息1mov ah,09hint 21hmov dl,0ahmov ah,02hint 21hsettime:mov si,offset tenhour;设定时间mov ah,01hint 21hcmp al,0dhjz forever1cmp al,'0'jc error2 ;如果输入不合法,报错cmp al,'3'jnc error2mov [si],alinc sicmp al,'2'jz ershimov ah,01h;如果小时高位为1,;低位可以设置0~9int 21hcmp al,0dhjz forever1cmp al,'0'jc error2cmp al,'9'+1jnc error2mov [si],alinc sijmp fenershi: m ov ah,01h;如果小时高位为2,低位可以设置0~4 int 21hcmp al,0dhjz forever1cmp al,'0'jc error2cmp al,'4'jnc error2mov [si],alinc sijmp fenfen: mov ah,01h;分高位可设置0~5int 21hcmp al,0dhjz forever1cmp al,':'jnz error1mov [si],alinc simov ah,01hint 21hcmp al,0dhjz forever1cmp al,'0'jc error1cmp al,'6'jnc error1mov [si],alinc si zcy4: mov ah,01h ;分低位0~9int 21hcmp al,0dhjz forever1cmp al,'0'jc error1cmp al,'9'+1jnc error1mov [si],alinc sijmp zcysettime2:jmp settime;用来跳转接力error2: jmp error1forever1:jmp next2zcy: mov ah,01h;秒高位可设置0~5int 21hcmp al,0dhjz forever1cmp al,':'jnz error1mov [si],alinc simov ah,01hint 21hcmp al,0dhjz forever1cmp al,'0'jc error1cmp al,'6'jnc error1mov [si],alinc simov ah,01h;秒低位可设置0~9int 21hcmp al,0dhjz forever1cmp al,'0'jc error1cmp al,'9'+1jnc error1mov [si],alinc sijmp next2error1: mov dl,0ah;用来报错:设置时间不合法mov ah,02hint 21hmov dx,offset msg2;打印提示信息2mov ah,09hint 21hmov dl,0ahmov ah,02hint 21hjmp settimesettime3: jmp settime2;跳转接力next2: MOV AX,0003H;做时钟显示初始化INT 10H;清屏显示mov dl,0ahmov ah,02hint 21hmov dx,offset msg3;打印提示信息3mov ah,09hint 21hmov dl,0ahmov ah,02hint 21hforever:mov bx,offset tenhour;这个程序段循环执行mov cx,8cmp tenhour,'2';如果超过24点,置为0点jnz dispclkcmp hour,'4'jnz dispclkmov tenhour,'0'mov hour,'0'dispclk:mov dl,[bx];用来显示当前时间call dispcharinc bxloop dispclk;调用显示子程序,显示初始状态时间,;比如”11:11:11"mov dl,0dh;输出一个换行call dispcharxor al,al ;读键盘缓冲区mov ah,0bhint 21hcmp al,0FFHjnz next3mov ah,08h;取其字符int 21hcmp al,03h;Ctrl+C退出jz stopcmp al,'s';S/s设定时间jz settime3cmp al,'S'jz settime3cmp al,0dhjnz next3mov dl,0ah;回车则使用秒表功能mov ah,02hint 21hjmp forevernext3: mov al,secondnext: cmp al,second;判断second是否发生变化je next;如果没有,循环比较jmp forever;如果有变化,刷新输出stop: mov dx,offset msg4;打印提示信息4 mov ah,09hint 21hmov dl,0ahmov ah,02hint 21hpop dx;恢复中断向量pop dsmov al,8mov ah,25hint 21hmov ah,4chint 21htimer proc far;中断程序timerpush axdec count100;计数100次jnz timerx;如果计数小于100,跳出中断mov count100,100;否则重置count100<=100;1s已经到达inc second;加一秒cmp second,'9';判断大小,用于进位,以下原理相同jle timerxmov second,'0'inc tenseccmp tensec,'6'jl timerxmov tensec,'0'inc minutecmp minute,'9'jle timerxmov minute,'0'inc tenmincmp tenmin,'6'jl timerxmov tenmin,'0'inc hourcmp hour,'9'ja adjhourcmp hour,'3'jnz timerxcmp tenhour,'1'jnz timerxmov hour,'1'mov tenhour,'0'jmp short timerx ;段内短转移adjhour:inc tenhourmov hour,'0'timerx: mov al,20hout 20h,al;主PIC口地址pop ax;出栈恢复iret;中断返回timer endpdispchar proc near;显示子函数push bxmov bx,0mov ah,02hint 21h ;DOS功能调用,输出DL内容pop bxretdispchar endpcode endsend start五、实验结果(反色)这幅图是运行程序之后,设定时间,输入的时间不合法的截图。