2. 中断

几个概念

Polling (轮询)

定义

轮询设备的状态,确保它们正常工作

特点

  • 可以实现简单、可靠的设备管理

  • 消耗大量的处理器时间

中断

定义

外部设备通过向处理器发送信号打断正在运行的程序

特点

  • 异步的,由外部事件触发

实例

  1. 移动鼠标

  2. 使用键盘

  3. 打印

结果

  1. 当前指令被打断

  2. 保护当前指令的状态,八个寄存器被放入

  3. 寄存器

  • LR(Link)被设为0xFFFFFFF9

  • IPSR (Interrupt Program Status Register) 被设为Interrupt Number

  • PC(Program Counter)加载Interrupt vector

比较

  • 中断是一种事件驱动的控制方式,当一个事件发生时(例如外部设备发出的信号),处理器会暂停当前执行的程序,转而执行与该事件相关的中断服务程序(ISR)。ISR执行完毕后,处理器会恢复之前的执行状态,继续执行被中断的程序。中断具有实时响应、低处理器占用率等优点,适用于需要快速响应外部事件的应用场景。

  • 轮询是一种基于循环的控制方式,程序会周期性地检查某个条件是否满足,然后决定下一步操作。轮询通常在一个无限循环中执行,会占用处理器的大量时间。轮询适用于处理器资源较为充足,但需要周期性检查某个条件的应用场景。

分类 中断 轮询
背景 在需要时调用处理器 定期查询
机制 机制 协议
Servicing Interrupt Handler CPU

中断处理程序设计

  • Let us consider a main process with an interrupt, where the main process is to input 10 random numbers with range [0, 100], and the interrupt is to input {$11^2 , 12^2 , 13^2 , … , 20^2$} once the input number in the main process is out of range.

C++程序(不确定能不能跑)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include<iostream>
#include<vector>
#include<Windows.h>

Using namespace std;

extern vector<int> Register(10,0); //仿真寄存器
extern vector<int> Stack(10,0); //仿真栈

/*保护状态,把数据从寄存器放到栈中*/
void Protect()
{
	Sleep(2000); // 延迟2s
	cout << "Start to protect Status! \n";

	for (int m=0;m<10;m++)
	{
		Stack[m] = Register[m];
	}

	Sleep(2000);
	cout << "Finish the protect process! \n";
}

/*恢复状态,把数据从栈放到寄存器中*/

void Recover()
{
	Sleep(2000);
	cout << "Begin to Recover State!\n";
	for (int n=0;n<10;m++)
	{
		Register[n] = Stack[n];
		Stack[n] = 0;
	}
	Sleep(2000);
	cout << "Finish the Recover Process!\n";
}

int main(void)

{
	int Flag = 0; //中断标志位
	char Choice[] = "N"; // 决定打开还是关闭“中断”进程

	cout << "Please indicate whether or not to switch on Interrupt (Y; on , N:off): \n";
	cin >> Choice;
	
	if strcmp((Choice,"Y") == 0)
	{
		Flag = 1;
	}

	for (int i=0;i<10;i++)
	{
		cout << "Please insert number" " " << i + 1 << ":" << endl;
		cin >> tem;
		cout << "\n";

		if ((tem > 100) || (tem < 0))
		{
			cout << "Out of range. Interrupt is triggered! \n";
			if (Flag == 1)
			{
				Protect();
				Sleep(2000);
				cout << "Execute Interrupt!\n";
				Interrupt();
				Sleep(2000);
				cout << "Interrupt is finished";
				Recover();
				i-=1;
				continue;
			}
			else
			{
				Sleep(1000);
				cout << "Interrupt is switched off!\n"
			}
		}
	}
	// Output the 10 numbers
	cout << "The input 10 numbers are:\n";
	for (int j=0;j<10;j++)
		cout << Register[j] << "\t";
	return 0;
}

汇编程序

中断的情况

  • 除法溢出时,就会中断

程序-输出overflow

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
code segment             ; 开始定义代码段
start:                   ; 定义程序入口标签
    mov as, cs           ; 将代码段的段地址 CS 赋值给 AS 寄存器
    mov ds, as           ; 将 DS 寄存器的值设置为 AS 寄存器的值,用于访问数据段
    mov si, offset do0   ; 将标签 do0 的偏移地址赋值给 SI 寄存器

    ; 将 ES 寄存器的值设置为 0,用于访问内存地址 0 - FFFFH
    mov ax, 0
    mov es, ax

    ; 将 DI 寄存器的值设置为内存地址 200H,用于存储数据
    mov di, 200h

    ; 将 CX 寄存器的值设置为标签 do0end 和 do0 之间的字节数,
    ; 用于循环复制数据到 DI 所指向的内存地址
    mov cx, offset do0end - offset do0

    ; 将处理器的方向标志位 DF 清零,设置为正向操作
    cld 

    ; 重复执行将源地址(SI)所指向的数据复制到目标地址(DI)所指向的内存地址
    ; 的操作,重复次数为 CX 寄存器的值
    rep movsb

    ; 将 ES 寄存器的值设置为 0,用于访问内存地址 0 - FFFFH
    mov ax, 0
    mov es, ax

    ; 将内存地址 0 处的值设置为 200H,用于存储数据
    mov word ptr es:[0*4], 200h 

    ; 将内存地址 2 处的值设置为 0,用于存储数据
    mov word ptr es:[0*4+2], 0

    ; 调用 DOS 中断 21H,功能码为 4C00H,用于结束程序并返回操作系统
    mov ax, 4c00h
    int 21h

; 定义标签 do0,用于显示字符串
do0:
    jmp short do0start    ; 无条件跳转到标签 do0start
    db "overflow!"        ; 字符串 "overflow!",以字节方式存储

; 定义标签 do0start,用于显示字符串
do0start:
    mov ax, cs            ; 将代码段的段地址 CS 赋值给 AX 寄存器
    mov ds, ax            ; 将 DS 寄存器的值设置为 AX 寄存器的值,用于访问数据段
    mov si, 202h          ; 将偏移地址 202H 赋值给 SI 寄存器,用于读取数据

    mov ax, 0b800h        ; 将文本缓冲区地址 0B800H 赋值给 AX 寄存器
    mov es, ax            ; 将 ES 寄存器的值设置为 AX 寄存器的值,用于访
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy