汇编学习笔记(完结篇)

2019-12-27  本文已影响0人  Jesse_996

内中断

对于8086,当cpu内部有下面的情况发生时,将产生相应的中断:

  1. 除法错误,如执行div时产生的除法溢出
  2. 单步执行
  3. 执行into指令
  4. 执行int指令

中断类型码是一个字节型数据, 通过中断类型码可以知道中断源,也可以定位中断处理程序。

cpu用8位中断类型码通过中断向量表找到相应的中断处理程序的入口地址。
中断向量表在内存中保存,放着256个中断源所应对的入口地址的列表。
对于8086,中断向量表指定放在内存地址0处。从内存0000:0000到0000:03FF的1024个单元中存放着向量表。这是规定。一个表项占2个字,即4字节,高地址放段地址,地址值放偏移地址。

中断过程

  1. 取得中断类型码N
  2. pushf
  3. TF=0,IF=0
  4. push CS
  5. push IP
  6. IP=N*4 ; CS= N*4+2

TF设为0的原因:避免cpu在执行中断处理程序的时候发生单步中断。
IF设为0的原因:在进入中断处理程序后,禁止其它的可屏蔽中断。

中断处理程序的步骤:

  1. 保存用到的寄存器
  2. 处理中断
  3. 恢复用到的寄存器
  4. 用iret指令返回

iret指令相当于:

pop IP
pop CS
popf

一般情况,cpu在执行完当前指令后,如果检测到有中断,就相应中断。但有些情况下,即使发生了中断,也不会相应。比如:在执行完向ss寄存器传送数据后,即使发生中断,也不会相应。这是因为对ss和sp的操作要连续完成,中间不能停,即执行完向ss传送数据后如果遇到中断,cpu不会相应,而是继续执行下一条指令之后才相应。所以设置ss和sp的指令要连续存放,使得设置sp的指令紧接着设置ss的指令执行。

int指令

int n相当于引发一个n号中断的中断过程。int指令的最终功能和call类似,都是调用一段程序。

端口

pc上,和cpu通过总线相连的芯片除了各种存储器外,还有其他各种芯片。这些芯片都和cpu的总线相连;cpu对它们进行读写的时候都是通过控制线向它们所在的芯片发出端口读写命令。这些外设接口芯片内部有入肝寄存器,cpu将这些寄存器当作端口来访问。

对端口的读写不能用mov,push,pop等指令。端口的读写命令只有两条:inout
in和out指令中,只能用ax或al来存放从端口中读入的数据或要发送到端口中的数据。访问8位端口时用al,16位用ax。

对0~255以内的端口进行读写:
in al,20h :从20h端口读入一个字节
out al,20h :从20h端口写入一个字节

对256~65535的端口进行读写时,端口号放在dx中:

mov dx,3f8h
in al,dx
out dx,al

shl和shr

shl是逻辑左移,功能为:

  1. 将一个寄存器或者内存单元中的数据向左移动
  2. 将最后移出的一位

外中断

外设的输入不是直接送入内存和cpu的,而是送入相关的接口芯片的端口中;cpu向外设输出也是先送到端口,再由相关的芯片送到外设。cpu还可以想外设输出控制命令,也是先送到端口。

外中断信息

我们现在知道外设的输入被存在端口中,但外设的输入随时可以到达,cpu怎么知道并及时处理的呢?
cpu通过外中断来处理。

外中断分为以下两类:

  1. 可屏蔽中断:
    cpu可以不响应中断。cpu是否响应可屏蔽中断,看flag中的IF位。如果IF=1,就中断,否则不中断。
    现在我们可以解释中断过程中将IF设为0的原因了:在进入中断处理程序后,禁止其它的可屏蔽中断。

    • sti:设置IF=1,允许中断发生
    • cli:设置IF=0,禁止中断发生
      这两条指令只能在内核态模式下执行,不可以在用户模式下执行。
      CLI 全称 Clear Interupt
      STI 全称 Set Interupt
      CLD 全称 Clear Director
      STD 全称 Set Director
  2. 不可屏蔽中断:
    对于8086,不可屏蔽中断的中断类型码固定为2。

几乎所有由外设引发的外中断,都是可屏蔽中断。

pc键盘的处理过程

按下一个键,产生一个扫描码,称为通码,送到相关接口芯片寄存器中,地址为60h。松开一个键也产生一个扫描码,称为断码。
断码 = 通码 + 80h
键盘的输入到达60h时,相关芯片就会向cpu发出中断类型码为9的可屏蔽中断信息。cpu检测到该中断信息后,若IF=1,则相应中断,转去执行int 9中断例程。
BIOS提供了int 9中断例程,主要工作是:

  1. 读出60h端口中的扫描码
  2. 如果是字符键的扫描码,将该扫描码和它所对应的字符码(ASCII码)送入内存中的BIOS键盘缓冲区;如果是控制键(如Ctrl)和切换键(如CapsLock)的扫描码,则将其转变为状态字节(用二进制位记录控制键和切换键状态的字节)写入内存中存储状态字节的单元。
  3. 对键盘系统进行相关的控制,比如向相关芯片发出应答信息。

直接定址表

数据标号:在标号后没有:,如a dw 0,这种标号记录了存储单元的地址和长度,不仅仅表示地址。
在任何段中,都可以使用数据标号来描述存储数据的单元的地址和长度。而在后面加有:的地址标号,只能在代码段中使用,不能在其它段中使用。
如果想在代码段中直接使用数据标号访问数据,则 需要用伪指令assume将标号所在的段和一个段寄存器联系起来,否则编译器在编译的时候无法确定标号的段地址在哪一个寄存器中,但不是说用了assume后,段寄存器中真的就会存放该段的地址。我们要在程序中手动进行设置。

可以将标号当作数据来定义,此时编译器将标号所表示的地址当作数据。

上一篇下一篇

猜你喜欢

热点阅读