一、实验目的
- 学会分析和理解给定的编程问题;
- 掌握中断驱动的基本原理;
- 掌握键盘数据寄存器(KBDR)及键盘状态寄存器(KBSR)工作基本原理;
- 掌握输出数据寄存器(DDR)及输出状态寄存器(DSR)工作基本原理;
- 利用LC-3设计并编写用户程序及中断程序。
二、实验内容
1.实验背景
在计算机科学中,一个中断就是有硬件和软件发起的一个事件,表明需要立即处理。
高优先级的条件下一个中断通知处理器需要中断正在运行的程序,处理器挂起正在处理的行为,保存执行程序的状态,然后执行一个小的中断处理程序(中断服务程序)来处理事件。
中断是临时的,当处理器执行完中断处理程序后,处理器继续执行之前被中断的程序,中断分硬件中断和软件中断。
2.实验描述
表明中断驱动的输入、输出可以中断一个正在运行的程序,执行中断服务程序,返回被中断的程序,从被中断位置下一个地址继续执行(好像什么也没发生似的)。实验中使用键盘作为输入设备,中断正在运行的程序。
3.实验任务
包括以下三部分:
A.用户程序
用户程序将会包含连续地输出纵横交替的ICS
,通过交替输出两个不同行,如下:
确保输出不至于太快,以至于肉眼不能察觉。用户程序应该包含以小段代码用于每行间的计数,间隔为从25000
开始倒计时输出在屏幕上。
B.键盘中断服务程序
键盘中断服务程序将会简单地在屏幕上写上十次,用户随机输入的字符并以Enter(x0A)
结束。
中断服务程序中不能使用TRAP指令。如在屏幕上显示一个字符,必须检测先DSR
寄存器,然后写进DDR
寄存器,并且也不可以调用 TRAP x21(OUT)
,或者其它TRAP
程序。
C.操作系统支持的代码
LC-3上没有安装windows或Linux,所以必须要求在用户程序代码前先做到以下三个步骤。
- 正常情况下,操作系统将会先安装一些栈空间,所以当中断发生的时候
PC
和PSR
可以被放进栈中(当程序执行RTI
,PC
和PSR
都会被弹出栈,处理器返回到执行被中断的程序)由于没有操作系统,请先把R6
初始化为x3000
,表示一个空的栈。 - 正常情况下,操作系统会建立中断向量表,它包含对应中断服务程序的起始地址,你必须为键盘中断先建立一个中断向量表。中断向量表的开始地址是
x0100
,键盘中断的中断向量是x80
。你必须在中断向量表提供一个入口供本实验使用。 - 操作系统应该设置
KBSR
的IE(Interrupt Enable)位,这个也由你实现。
三、实验步骤与结果
程序实现思路及流程图
1.用户程序思路和流程图
要实现从键盘输入一个字符后执行中断程序,就需要将中断程序的起始地址写入键盘的中断矢量表中,且要将KBSR的中断使能位设置为1。具体步骤如下(Fig. 1):
首先要进行预处理:
- 把
R6
初始化为x3000
,表示一个空栈,用于存放PC
和PSR
等需要保存和恢复的内容。 - 将中断服务程序的入口地址
x2000
和键盘的中断矢量x0180
联系起来。 - 将
KBSR
的中断使能位设置为1
然后,依次完成以下三个步骤:
- 在用户程序中,连续地输出纵横交替的
ICS
; - 在读入来自键盘的字符后,保护现场并进入中断服务子程序
- 在子程序中,如果键入回车,则输出十个之前键入的字符,恢复现场,并回到用户程序,重复3。
Figure 1用户程序的流程图
2.中断服务子程序的思路和流程图
该程序分为以下几个步骤(Fig. 2):
- 压栈保存寄存器(保护现场)
- 反复检测
KBSR[15]
,如果KBSR[15]=1
,则检测键入的字符是否是回车。如果是回车,则执行3;如果不是回车,则更新待输出的字符后回到2。 - 连续输出十个之前在用户程序键入的字符并换行。
- 退栈以恢复寄存器(恢复现场)并执行
RTI
。
实验结果
实验结果如下:
-
无键盘读入时,交替输出“
ICS
”;从键盘读入一个字符‘5
’后暂停(Fig. 3)。
Figure 3 读入字符‘5
’以后,键入回车以前的情景 -
键入回车,连续输出10个‘
5
’以后又回到最初的样子:交替输出“ICS
”(Fig. 4)。
Figure 4键入回车以后的情景
四、完整代码
lab5_user_program
; author: CAO-Wuhui
; date: 2021.6.19
; This is the program of user
.ORIG x3000
LD R6,STACK ; initialize the stack pointer saved in R6
; set up the keyboard interrupt vector table entry
LD R1,ENTRANCE ; Interrupt Vector
LD R2,INTV ; The entrance of the interrupt service routine
STR R1,R2,#0 ; If there is something input from keyboard, PC will go to x2000
; enable keyboard interrupts
LD R3,IE
STI R3,KBSR ; KBSR[14] = 1
; Start of actual user program to print ICS checkerboard
PRINT LEA R0,STR1
TRAP x22 ; Print the first string
LEA R0,STR2
JSR DELAY
TRAP x22 ; Print the second string
JSR DELAY
BRnzp PRINT ; Continue printing
HALT
DELAY ST R1, SaveR1
LD R1, COUNT
REP ADD R1,R1,#-1
BRp REP
LD R1, SaveR1
RET
STR1 .STRINGZ "ICS ICS ICS ICS ICS ICS\n"
STR2 .STRINGZ " ICS ICS ICS ICS ICS\n"
IE .FILL x4000 ;0100 0000 0000 0000
KBSR .FILL xFE00
KBDR .FILL xFE02
COUNT .FILL #25000
INTV .FILL x0180
ENTRANCE .FILL x2000
SaveR1 .FILL #0
STACK .FILL x3000
.END
lab5_interrupt_service_routine.asm
.ORIG x2000 ; the code
ADD R6,R6,#-1
STR R0,R6,#0
ADD R6,R6,#-1
STR R1,R6,#0
ADD R6,R6,#-1
STR R2,R6,#0
ADD R6,R6,#-1
STR R3,R6,#0
LOOP ST R0,SaveR0
CHECK LDI R1,KBSR ; Check the value of KBSR[15]
ADD R1,R1,#0 ; If KBSR[15] = 1, break
BRzp CHECK ;
LDI R0,KBDR
LD R2,_ENDLINE ;
ADD R2,R2,R0
BRnp LOOP
AND R3,R3,#0
ADD R3,R3,#10
P_LOOP LD R0,SaveR0
START LDI R1,DSR ; Check the value of DSR[15]
BRzp START ; If DSR[15] = 1, break
STI R0,DDR
ADD R3,R3,#-1
BRp P_LOOP
P_ENDL LD R0,ENDLINE
LDI R1,DSR
BRzp P_ENDL
STI R0,DDR
LDR R3,R6,#0
ADD R6,R6,#1
LDR R2,R6,#0
ADD R6,R6,#1
LDR R1,R6,#0
ADD R6,R6,#1
LDR R0,R6,#0
ADD R6,R6,#1
RTI
; buffer space as required
_ENDLINE .FILL xFFF6 ; _'\n'
ENDLINE .FILL x000A ; '\n'
SaveR0 .FILL #0
KBSR .FILL xFE00
KBDR .FILL xFE02
DSR .FILL xFE04
DDR .FILL xFE06
.END