在计算机科学中,一个中断就是有硬件和软件发起的一个事件,表明需要立即处理。
高优先级的条件下一个中断通知处理器需要中断正在运行的程序,处理器挂起正在处理的行为,保存执行程序的状态,然后执行一个小的中断处理程序(中断服务程序)来处理事件。
中断是临时的,当处理器执行完中断处理程序后,处理器继续执行之前被中断的程序,中断分硬件中断和软件中断。
表明中断驱动的输入、输出可以中断一个正在运行的程序,执行中断服务程序,返回被中断的程序,从被中断位置下一个地址继续执行(好像什么也没发生似的)。实验中使用键盘作为输入设备,中断正在运行的程序。
包括以下三部分:
用户程序将会包含连续地输出纵横交替的ICS
,通过交替输出两个不同行,如下:
确保输出不至于太快,以至于肉眼不能察觉。用户程序应该包含以小段代码用于每行间的计数,间隔为从25000
开始倒计时输出在屏幕上。
键盘中断服务程序将会简单地在屏幕上写上十次,用户随机输入的字符并以Enter(x0A)
结束。
中断服务程序中不能使用TRAP指令。如在屏幕上显示一个字符,必须检测先DSR
寄存器,然后写进DDR
寄存器,并且也不可以调用 TRAP x21(OUT)
,或者其它TRAP
程序。
LC-3上没有安装windows或Linux,所以必须要求在用户程序代码前先做到以下三个步骤。
PC
和PSR
可以被放进栈中(当程序执行RTI
,PC
和PSR
都会被弹出栈,处理器返回到执行被中断的程序)由于没有操作系统,请先把R6
初始化为x3000
,表示一个空的栈。x0100
,键盘中断的中断向量是x80
。你必须在中断向量表提供一个入口供本实验使用。KBSR
的IE(Interrupt Enable)位,这个也由你实现。要实现从键盘输入一个字符后执行中断程序,就需要将中断程序的起始地址写入键盘的中断矢量表中,且要将KBSR的中断使能位设置为1。具体步骤如下(Fig. 1):
首先要进行预处理:
R6
初始化为x3000
,表示一个空栈,用于存放PC
和PSR
等需要保存和恢复的内容。x2000
和键盘的中断矢量x0180
联系起来。KBSR
的中断使能位设置为1
然后,依次完成以下三个步骤:
ICS
;该程序分为以下几个步骤(Fig. 2):
KBSR[15]
,如果KBSR[15]=1
,则检测键入的字符是否是回车。如果是回车,则执行3;如果不是回车,则更新待输出的字符后回到2。RTI
。实验结果如下:
无键盘读入时,交替输出“ICS
”;从键盘读入一个字符‘5
’后暂停(Fig. 3)。
Figure 3 读入字符‘5
’以后,键入回车以前的情景
键入回车,连续输出10个‘5
’以后又回到最初的样子:交替输出“ICS
”(Fig. 4)。
Figure 4键入回车以后的情景
; 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
.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