chapter12-chapter16

发布时间 2023-11-07 12:12:54作者: scrutiny-span

chapter12:内中断

中断:CPU不再接着刚执行完的指令向下执行,而是转去处理从CPU内部产生或者外部发送过来的一种特殊信息。中断信息可以来自CPU的内部和外部,来自CPU外部(比如说外设)的中断信息称之为外中断,这个章节主要讨论内中断

1.内中断的产生

对于8086CPU,当CPU内部有下面的情况发生的时候,将产生相应的中断信息。

  1. 除法错误:比如说执行div指令时产生的除法溢出,在8086CPU中中断类型码为0
  2. 单步执行:中断类型码为1。这个类型的中断用于实现Debug功能(单步跟踪程序的执行过程)
  3. 执行into指令:中断类型码为4
  4. 执行int指令:这个指令的格式为int n,指令中的n是一个立即数,是提供给CPU的中断类型码

中断信息中必须包含识别中断信息的来源(中断源)的编码,在8086CPU中用一个字节型的数据(即中断类型码)来标识中断信息的来源。

2.中断处理程序

处理中断信息的程序叫做中断处理程序。中断类型码的作用就是定位中断处理程序。CPU用8位的中断类型码通过中断向量表找到相应的中断处理程序的入口地址。

3.中断向量表

  1. 中断向量表就是中断向量的列表。中断向量就是中断处理程序的入口地址。即中断向量表就是中断处理程序入口地址的列表。
  2. 中断向量表示例:共计2^8=256个表项
    image.png
  3. 中断处理程序的入口地址的寻找:CPU用中断类型码通过查找中断向量表就可以得到中断处理程序的入口地址(入口地址包括段地址和偏移地址。一个表项占用两个字,高地址字存放段地址,低地址字存放偏移地址)。对于8086CPU,中断向量表存放在内存地址0处,从内存0000:0000到0000:03FF的1024个字节。

4.中断过程

  1. 下面是8086CPU在收到中断信息后,所引发的中断过程如下:
    1. 从中断信息中取得中断类型码
    2. 标志寄存器的值入栈(因为在中断过程中要改变标志寄存器的值,所以先将其保存在栈中)
    3. 设置标志寄存器的第八位TF和第九位IF的值为0
      (将TF设置为0的原因是避免CPU在执行中断处理程序的时候发生单步中断,IF设为0的原因是在进入中断处理程序后,不响应可屏蔽中断。)
    4. CS的内容入栈
    5. IP的内容入栈
    6. 从内存地址为中断类型码 * 4和中断类型码 * 4 + 2的两个字单元中读取中断处理程序的入口地址设置CS和IP
  2. 上述过程中,中断处理程序执行完后,CPU还要回过头来继续执行被中断的程序。所以在更新CS和IP的值之前,需要先将标志寄存器、旧CS、旧IP的值入栈,以便执行完中断处理程序可以恢复被中断程序的执行。这也叫做上下文恢复,在进程切换、函数调用、中断处理都有这个语义。

5.中断处理程序和iret指令

  1. 中断处理程序的编写步骤:
1. 保存用到的寄存器
2. 处理中断
3. 恢复用到的寄存器
4. 用iret指令返回
  1. iret指令的功能描述
;汇编语法描述
pop IP
pop CS
popf (f表示标志寄存器)

单步中断

  1. 单步中断的中断类型码为1,其所引发的中断过程如下:
    1. 取得中断类型码1
    2. 标志寄存器入栈,TF、IF设置为0
    3. CS、IP入栈
    4. (IP) = (1 * 4),(CS) = (1 * 4 + 2)
  2. CPU提供单步中断的功能:为单步跟踪程序的执行过程,提供了实现机制

chapter13:int指令

int指令也能引发内中断。

  1. int指令的格式:int n,n为中断类型码,它的功能是引发中断过程。CPU执行int n指令,相当于引发一个n号中断的中断过程(执行中断处理程序)。执行过程如下:
    1. 取得中断类型码n
    2. 标志寄存器入栈,IF=0,TF=0
    3. CS、IP入栈
    4. (IP) = (n*4),(CS)=(n * 4 + 2)
  2. int指令的最终功能是调用一段程序,和call指令相似。 可以在程序中使用int指令调用任何一个中断类型的中断处理程序

chapter14:端口

1.端口
  1. PC系统的接口卡和主板上,装有各种接口芯片。这些外设接口芯片的内部有若干寄存器,CPU将这些寄存器当作端口来访问。
  2. CPU可以直接读写以下三个地方的数据
    1. CPU内部的寄存器
    2. 内存单元
    3. 端口
  3. 端口的读写指令:in和out
    1. in表示从端口读取数据
    2. out表示往端口写入数据
  4. 示例:
    1. in al,60h:表示从60号端口读入一个字节
    2. out 20h,al:表示往20h端口写入一个字节
2.shl和shr指令

shl和shr都是逻辑移位指令。

  1. shl是逻辑左移指令,它的功能为:
    1. 将一个寄存器或者内存单元中的数据向左移位
    2. 将最后移出的一位写入CF中。(如果移动位数大于1,必须将移动位数放在cl中,即cx寄存器的低8位)
    3. 最低位用0补充
    mov al,01010001b
    shl al, 1
    
    mov al,01010001b
    mov cl, 3 ;移动位数大于3,所以需要将移动位数放在cl中
    shl al, cl
    
  2. shr是逻辑右移指令
    1. 将一个寄存器或者内存单元中的数据向右移位
    2. 将最后移出的一位写入CF中(如果移动位数大于1,必须将移动位数放在cl中)
    3. 最高位用0补充

chapter15:外中断

外设的输入不直接送入内存和CPU,而是送入相关的接口芯片的端口(寄存器)中。CPU向外设的输出也不是直接送入外设,而是先送入端口(寄存器)中,再有相关的芯片送到外设。CPU向外设输出控制命令也是如此。外中断比如说:

  1. 键盘输入:键盘输入将引发9号中断向键盘缓冲区写入,9号中断处理程序由BIOS提供
  2. 从键盘缓冲区中读取键盘输入:16号中断,由BIOS提供

来自CPU外部的中断信息叫做外中断

  1. 在PC机中,外中断源分为两类:
    1. 可屏蔽中断
    2. 不可屏蔽中断
1.可屏蔽中断
  1. 可屏蔽中断是CPU可以不响应的外中断,CPU是否响应可屏蔽中断,要看标志寄存器中的IF(Interrupt flag)位的信息。当CPU检测到可屏蔽中断信息时,如果IF为1,则CPU执行完当前指令后响应中断,引发中断过程。如果IF为0,则不响应可屏蔽中断。可屏蔽中断引发的中断过程如下所示:
    1. 通过数据总线将中断类型码送入CPU
    2. 标志寄存器入栈、IF=0、TF= 0
    3. CS、IP入栈
    4. (IP) = (n * 4),(CS) = (n * 4 + 2)
  2. 设置IF的指令如下
    1. sti:设置IF为1
    2. cli:设置IF为0
2.不可屏蔽中断
  1. 不可屏蔽中断是CPU必须响应的外中断,当CPU检测到不可屏蔽中断信息后,则在执行完当前指令后,立即响应,引发中断过程。对于8086CPU不可屏蔽中断的中断类型码固定为2,所以在中断过程中,不需要取中断类型码。 不可屏蔽中断的中断过程如下所示:
    1. 标志寄存器入栈、IF=0、TF= 0
    2. CS、IP入栈
    3. (IP) = (2 * 4),(CS) = (2 * 4 + 2)
3.CPU及时处理外设输入的过程
  1. 外设的输入送入相关的接口芯片的寄存器(端口)中
  2. 相关芯片将向CPU发出相应的外中断信息。CPU在执行完当前指令之后,可以检测到发送过来的外中断信息,引发中断过程,处理外设的输入。
4.PC机键盘的处理过程
  1. 键盘产生扫描码
  2. 扫描码送入60h端口
  3. 引发9号中断
  4. CPU执行int 9中断程序处理键盘输入

chapter16:直接定址表

1.描述了单元长度的标号

  1. 地址标号:仅仅表示了内存单元的地址
  2. 数据标号这种标号不仅表示内存单元的地址,还表示内存单元的长度(一个字节单,元还是一个字单元,还是一个双字单元)。使用这种包含单元长度的标号,可以使得我们以简洁的形式访问内存中的数据。示例如下:将code段中的a标号处的8个数据累加,结果存储到b标号处的字中
assume cs:code
code segment
    ; 标号a,描述了地址code:0,和从这个地址开始以后的内存单元都是字节单元
    a db 1,2,3,4,5,6,7,8
    ; 标号b,描述了地址code:8,和从这个地址开始以后的内存单元都是字单元
    b dw 0
start:  mov si, 0
        mov cx, 8
    s:  mov al, a[si]
        mov ah, 0
        ; 相当于add word ptr cs:[8], ax
        add b, ax
        inc si
        loop s

        mov ax, 4c00h
        int 21h
code ends

end start

2.直接定址表

  1. 依据数据直接计算出所要找的元素的位置的表,称其为直接定址表
  2. 程序入口地址的直接定址表:可以在直接定址表中存储各个子程序的地址,从而方便的实现不同子程序的调用
// 将子程序的入口地址存储在一个表中
table dw func1,func2,func3
// 调用对应功能的子程序
call word ptr table[bx]