日时钟中断:

系统日时钟中断源是系统8254 0#计数器,每55ms有一次中断请求。

lua 中断代码 中断代码8_中断向量

 中断类型码为08H

系统日时钟中断(8型中断服务子程序)处理流程:

(1)开中断保护现场,40H->DS

(2)对日时钟计数器进行一次加1计数

(3)执行INT 1CH

1CH为日时钟的外扩中断,用户可开发新的1CH中断

(4)向主8259A发出常规中断结束命令

MOV AL,20H

OUT 20H,AL

(5)恢复现场,执行IRET指令

例:利用PC系列机上的8254的0号定时计数器引发的日时钟中断,设计程序:每隔1S在PC终端屏幕上显示一行字符串'HELLO!',显示10行结束

(1)保存原来系统的1CH中断向量到数据段OLD1C双字单元

(2)置换1CH中断向量使其指向自己的中断服务子程序

(3)中断服务子程序每执行18次显示一次字符串

(4)在返回操作系统前恢复原来保存的1CH中断向量

数据段:

DATA SEGMENT USE16

MESG    DB   'HELLO!',0DH,0AH,'$'

OLD1C  DD   ?      ;保存1CH原本的中断向量,双字

ICOUNT DB 18    ;中断计数初值?

COUNT DB 10     ;显示行数

DATA ENDS

代码段:

CODE SEGMENT USE16

            ASSUME CS:CODE,DS:DATA

BEG:  MOV AX,DATA

             MOV DS,AX

             CLI  ;关中断

CLI关中断是防止在WRITE1C如果有日时钟中断的话,会访问1CH,所以会出现一边读一边写的情况,可能会出现问题。

READ1C不关中断也可以,因为如果在读取的过程中有日时钟中断,那么会执行默认的1CH,即什么也不做,没有影响。

             CALL READ1C;读取原本1CH的中断向量到OLD1C

             CALL WRITE1C;写入新的中断向量

             STI ;开中断

SACN:CMP COUNT,0

              JNZ SACN ;是否已经显示10行,否则一直在这等待

              CLI

              CALL RESET;恢复1CH中断向量

              STI

              MOV AH,4CH

              INT 21H

中断服务子程序SERVICE

SERVICE  PROC

                  PUSHA

                  PUSH  DS

                  MOV AX,DATA

                  MOV DS,AX     ;因为在写入1CH中断向量时,把代码段段基址赋给了DS,因为下面用到了数据段的变量,为了能够正确找到变量,所以需要把数据段段基址赋给DS,以防DS存的是代码段的段基址。

                  DEC ICOUNT

                  JNZ EXIT         ;ICOUNT初值为18,每次进入SERVICE中断服务子程序时,ICOUNT都要减1,当减到0时打印1行,并且把ICOUNT初值还原为18,COUNT减1;否则直接退出中断服务子程序

                 MOV ICOUNT,18

                 DEC COUNT 

                 MOV AH,9

                 MOV DX,OFFSET MESG

                 INT 21H

EXIT:        POP DS

                 POPA

   IRET 

SERVICE ENDP               

 READ1C子程序:

READ1C   PROC

                  MOV  AH,35H

                  MOV  AL,1CH 

                  INT 21H

                  MOV WORD PTR OLD1C,BX

                  MOV WORD PTR OLD1C+2,ES

                  RET

READ1C  ENDP

WRITE1C PROC子程序:

WRITE1C PROC 

              PUSH DS        ;在写中断向量时,会把中断服务程序的段基址赋给DS,但是DS原本存放的是数据段段基址,所以要在写中断向量的时候保护DS

              MOV AX,SEG SERVICE

              MOV DS,AX 

              MOV DX,OFFSET SERVICE

              MOV AH,25H

              MOV AL,1CH

              INT 21H

              POP DS

              RET

WRITE1C  ENDP              

RESET子程序:

RESET PROC

;这里不保护DS的原因是之后的代码中不会在用到代码段的变量了。

             MOV  DX,WORD PTR OLD1C 

             MOV  DS,WORD PTR OLD1C+2

             MOV AH,25H

             MOV AL,1CH

             INT 21H

             RET

RESET ENDP