汇编6

中断

CPU有这样一种功能:在执行完当前指令后,检测到cpu外部发送过来的或内部产生的一种特殊信息,且可以立即对接收到信息进行处理,这种信息呢,就叫中断信息。

内中断

当CPU内部有什么事情发生的时候,将产生需要马上处理的中断信息呢?对于8086来说,当cpu内部有下面的情况发生时,产生相应中断;

  1. 除法错误,比如,执行div指令产生的除法溢出;
  2. 单步执行;
  3. 执行into指令;
  4. 执行int指令。
    上面的四种中断源,在8086中中断类型码如下。
  5. 除法错误:0
  6. 单步执行:1
  7. 执行into指令:4
  8. 执行int指令,该指令的格式为int n,指令中的n为字节型立即数,是提供给CPU的中断类型码。
    cpu收到中断信息后,需要对中断信息进行处理,需要对不同的中断信息编写不同的处理程序。
    若要定位中断处理程序,需要知道它的段地址和偏移地址
    中断向量表就是中断向量的列表,中断向量就是中断处理程序的入口。
    enter description here

中断过程:

中断类型码->中断向量表->修改CS:IP->中断处理程序

  1. (从中断信息中)取得中断信息码;
  2. 标志寄存器的值入栈(因为在中断过程中要改变标志寄存器的值,所以先将其保存在栈中);
  3. 设置标志寄存器的第8位TF和第9位IF的值为0(以后解释)
  4. CS的内容入栈;
  5. IP的内容入栈;
  6. 从内存地址位中断类型码*4 和中断类型码*4+2的两个字单元中读取中断处理程序入口地址设置IP和CS。

中断处理程序

中断信息可能随时被检测到,所以中断处理程序必须一直存储在内存某段空间之中。中断处理程序入口地址,即中断向量,必须存储在对应表项中。

  1. 保存用到的寄存器;
  2. 处理中断
  3. 恢复用到的寄存器
  4. 用iret指令返回。
    iret:
    pop ip
    pop cs
    popf

经典除法中断(0号中断)

再实现

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
assume cs:code
code segment
start:
mov ax,cs
mov ds,ax
mov si,offset do0;要存的中断处理程序

mov ax,0
mov es,ax
mov di,200h;存放地址(这里随便放在了中断表的后面空闲位置中)

mov cx,offset do0end-offset do0;存放的量(编译器可以进行简单运算)
cld; cld是来控制重复移动时候的si 和di的递增方式即+1(用std是-1)。
rep movsb;逐字节移动复制

mov ax,0
mov es,ax
mov word ptr es:[0*4],200h;写入中断向量表入口地址ip
mov word ptr es:[0*4+2],0;cs

mov ax,4c00h
int 21h;这只是将中断处理程序写入的结束

do0:
jmp short do0start
db "overflow!!!"
db 0ach
do0start:
mov ax,cs
mov ds,ax
mov si,201h;o开始处

mov ax,0b800h;老规矩的显存修改
mov es,ax
mov di,12*160+36*2
mov ah,[si+24]

mov cx,12
s:
mov al,[si]
mov es:[di],al
mov es:[di+1],ah
inc si
add di,2
loop s

mov ax,4c00h
int 21h;中断处理结束

do0end:
nop
code ends
end start

效果:
enter description here

int

int n ;引发中断过程 过程:

  1. 取中断类型码n
  2. 标志寄存器入栈,TF=0,IF=0
  3. CS、IP入栈
  4. (IP)=(n*4),(CS)=(n*4+2)
  5. 执行中断处理程序
    1
    2
    mov word ptr es:[aaaa*4],200h;写入中断向量表入口地址ip
    mov word ptr es:[aaaa*4+2],0;cs
    aaaa是多少就是int多少

BIOS/DOS提供的中断例程

在系统的ROM中存放着一套程序,称为BIOS,主要有:

  1. 硬件系统的检测和初始化程序;
  2. 外部中断和内部中断的中断例程;
  3. 用于对硬件设备进行I/O操作的中断例程;
  4. 其他和硬件系统相关的中断例程。
    DOS中也提供了中断例程,DOS的中断例程就是操作系统向程序员提供的编程资源。

BIOS中断例程应用

int 10h的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
assume cs:code
code segment
start:
mov ah,2
mov bh,0
mov dh,5
mov dl,12
int 10h;解释:ah=2表示调用第10h号中断例程的2号子程序,功能为设置光标位置可以提供光标所在的行号、列号和页号作为参数。bh=0,dh=5,dl=12,设置光标到第0页,第5行,第12列。

mov ah,9;在光标位置显示字符
mov al,'a'
mov bl,11001010b;同显存设置颜色属性
mov bh,0
mov cx,3;字符重复个数
int 10h

mov ax,4c00h
int 21h
code ends
end start

enter description here

DOS中断例程应用

经典:

1
2
mov ax,4c00h
int 21h

int 21h ; DOS提供的中断例程,包含了很多子程序
我们使用4ch号功能,即程序返回功能

1
2
3
mov ah,4ch;程序返回功能号
mov al,0;返回值
int 21h

又如:
在屏幕的5行12列显示字符串“Welcome to cloud”
enter description here

端口

在访问端口的时候,cpu通过端口地址来定位端口。因为端口所在的芯片和cpu通过总线相连,所以,端口地址和内存地址一样,通过地址总线来传送。在pc系统中,cpu最多可以定位64KB个不同的端口。则端口地址的范围为0~65535。

对端口的读写不能用mov,push,pop等内存读写指令。只能用inout这两条,分别用于从端口读取数据和向写入数据。

在in和out指令中,只能使用ax或al来存放从端口中读入的数据或要发送到端口中的数据。访问8位端口时用al,访问16位端口时用ax

对0~255以内的端口读写:
in al,20h
out 20h,al

对256~65535端口读写,端口号放在dx中
mov dx,3f8h
in al,dx
out dx,al

CMOS-RAM

PC机中,有一个CMOS RAM芯片,一般简称位CMOS。特征如下:

  1. 含一个实时钟和一个有128个存储单元的RAM存储器(早期为64个字节)。
  2. 该芯片靠电池供电。所以关机后其内部的实时钟仍可正常工作,RAM中的信息不丢失。
  3. 128个字节的RAM中内部实时钟占用0~0dh单元保存信息,其余大部分单元用于保存系统配置信息,供系统启动时BIOS程序读取。BIOS也提供了相关的程序,使我们可以再开机的时候配置CMOS RAM中的系统信息。
  4. 该芯片内部有两个端口,端口地址为70h和71h。CPU通过这两个端口来读写CMOS RAM。
  5. 70h为地址端口,存放要访问的CMOS RAM单元的地址;71h为数据端口,存放从选定的CMOS RAM单元中读取的数据,或要写入到其中的数据。可见,CPU对CMOS RAM的读写分两步进行,比如,读CMOS RAM的2号单元:
    1. 将2送入端口70h;
    2. 从端口71h读出2号单元的内容。

shl/shr

shr和shl是逻辑移位指令
shl逻辑左移

  1. 将一个寄存器或内部单元中的数据向左位移;
  2. 将最后移出的一位写入CF中;
  3. 最低位用0补充;
  4. 如果移动位数大于1时,必须将移动位数放在cl中。
    shr是逻辑右移指令,与shl相反。
  5. 将一个寄存器或内存单元的数据向右移位。
  6. 将最后移出的一位写入CF。
  7. 最高位用0补充。
    用法与shl一致。

实战

enter description here
在屏幕中间显示当前月份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
assume cs:code
code segment
start:
mov al,8
out 70h,al
in al,71h

mov ah,al
mov cl,4
shr ah,al;取前4位BCD码
and al,00001111b;取后4位BCD码

add ah,30h
add al,30h

mov bx,0b800h
mov es,bx
mov byte ptr es:[160*12+40*2],ah
mov byte ptr es:[160*12+40*2+2],al

mov ax,4c00h
int 21h
code ends
end start

enter description here

外中断

  • 可屏蔽中断
    sti:IF置为1,响应中断
    cli:IF置为0,不响应可屏蔽中断
  • 不可屏蔽中断
    8086CPU,不可屏蔽中断的中断类型码固定为2
    还是in,out

---------------THEEND---------------