汇编味小饼干
汇编味浓缩饼干
为备考而制作的知识点汇总,方便考生快速而准确的浏览到汇编语言中的重点。内容简单干脆,小巧精美。希望每一个阅读的考生都能像嚼饼干一样轻松的拿下汇编。
本汇编知识点汇总基于8086操作系统总结而成,参考教科书《汇编语言》·王爽著。
基础知识
一些8086组成原理的基本介绍,属于汇编中的开胃小菜。
储存单元
-
一个双字(dword)有两个字(word)
双字:4f 00 24 c2
字:24 c2
-
一个字(word)有两个字节(byte)
字:24 c2
字节:24、c2 (十六进制下)
-
一个字节(byte)有8个位(bit)
字节:c2
位:11000010 (1个低位字节十六进制展开对应4个二进制位,一个字节展开就是8个位)
通常来说,8086的内存单元即指代的是一个字节。
注意8086机器大多采用小端序,即低位在前高位在后。所谓低位字节/字即右半部分,高位即左半部分。
比如AX=100111000100000,则填充AX为16位:01001110 00100000,AH=01001110,AL=00100000。
CPU的读写功能
CPU对内存及存储器的读写依赖于三根总线:
- 地址总线
- 数据总线
- 控制总线
具体工作流程如下:
- 通过地址线发出地址信息
- 通过控制线发出内存读写命令
- 通过数据线传入/传出数据
三大总线
总线的根数成为宽度。
地址总线的宽度决定了它的寻址能力。比如地址总线宽度为10,说明有10根线,每根线对应高低电平可以视为二进制,那么这个地址总线就具备2n的寻址能力。
数据总线的宽度决定了它的传输能力。8086CPU的数据总线宽度为16,有16根线,那么每次就能传送16位数据,也就是两个字节/一个字。
控制总线是一些不同控制线的集合,有多少根控制总线,意味着CPU对外部器件提供了多少种控制。
16位CPU
8086是16位机,经过对三大总线的宽度介绍,我们现在可以很轻松的理解16位结构(16位机、字长为16位)的含义。概括的说,有以下三个特性:
- 运算器一次最多可以处理16位的数据。
- 寄存器最大宽度为16位。
- 寄存器与运算器之间的通路为16位。
存储器芯片与内存地址空间
一般由读写属性可分为两类:随机存储器(RAM)和只读存储器(ROM)。随机存储器可读可写,但是必须带电存储,关机后存储内容丢失;只读存储器只能读不能写,关机后内容不丢失。
基于以上特性,RAM常被用来存放供CPU使用的绝大部分程序与数据,包括主存储器、显存和接口卡上的存储器。而ROM常被用来存储BIOS(Basic Input/Output System)。
地址空间分配如下:
- 0~7fffh的32kb为主随机存储器的地址空间
- 8000h~9fffh的8kb空间为显存地址空间
- a000h~ffffh的24kb为各个ROM的地址空间
8086与物理地址
学会计算实际的物理地址是汇编中的基础操作。在8086中,物理地址=段地址*16+偏移地址。
我们以段地址寄存器DS和偏移寄存器DI举例。
计算时用DS*16+DI,在十六进制下即将DS中的四位十六进制数左移一位与DI中的地址相加得到实际地址。
由于段地址*16必然是16的倍数,所以一个段的起始地址也一定是16的倍数;同时,偏移地址为16位,16位地址的寻址能力为64kb,即一个段的最大长度为64kb。
210 = 1024
FFFFH = 1111 1111 1111 1111 = 216 = 26 * 1024 = 64kb
寄存器
介绍了CPU中各个寄存器的作用,基础且重要,不过也很简单。
AX寄存器·Accumulator
AX是四大通用寄存器中的一员(AX、BX、CX、DX)
此外,AX也被称为累加器,在许多运算过程中都用于存储和操作数据。
除了常规的加减法外,在使用mul
指令执行乘法操作时:
- 被乘数为8位,放置在AL中;调用
mul 乘数
,最终结果存储在AX内。 - 被乘数为16位,放置在AX中;调用
mul 乘数
,最终结果低位储存在AX内,高位储存在DX内。
使用div
指令执行除法操作时:
- 除数为8位,则被除数16位默认在AX中;调用
div 除数
,最后AH存储余数,AL存储商。 - 除数为16位,则被除数32位默认高位在DX,低位在AX;
div 除数
,最后DX存储余数,AX存储商。
BX寄存器·Base
BX也是通用寄存器。
BX也被称为基址寄存器,可以用来进行内存寻址。比如8086允许DS:[BX]的寻址调用,而DS:[AX]的使用是非法的。
同样可以进行内存寻址的还有SI、DI、BP寄存器。
CX寄存器·Count
CX寄存器也是一个通用寄存器。
CX又被称为计数寄存器,最重要的用途就是用来循环计数。当调用loop 标号
指令时,会执行以下操作:
-
CX = CX - 1
-
CX==0 ? 执行下一条指令 : jmp 标号
即检查CX的值是否为0,如果为0则退出循环,否则跳转回标号继续循环。
值得注意的是如果CX已经等于0,再去进行loop
调用,那么CX会先递减并发生下溢舍去符号位变为FFFFh
,然后跳出循环检测为假陷入无限循环。
此外,再进行字符串处理时,比如调用cmpsb
,movsb
等指令时,CX也用来处理要储存的字符串的长度。rep
会根据CX的值来决定循环次数。
DX寄存器·Data
DX也是通用寄存器。
同时,DX也被称为数据寄存器。在前文的乘除法操作中,DX常和AX一起使用来存储数据。
此外,在进行IO端口映射时,DX也用于做端口地址寄存器。调用in
和out
指令端口映射时,用DX储存要访问端口的地址。
在某些时刻DX还能做数据传输操作的来源或者地址,比如调用int 21h
中断例程时,常用DX存储要打印或者输入的字符串内存地址。
SI寄存器·Source Index
SI寄存器,常被称为源索引寄存器。在8086中主要用于字符串操作和间接寻址。
- 字符串操作:在执行字符串指令时,SI寄存器通常用作源字符串的偏移量。例如,在执行
MOVSB
(移动字符串字节)或STOSB
(存储字符串字节)等指令时,ES:SI寄存器指向源字符串的当前位置,而DS:DI则指向要转移的目标位置。 - 间接寻址:SI寄存器和BX一样,可以用于间接寻址模式。其中它作为基地址寄存器,与偏移量结合来形成完整的内存地址。
- 数据传输:在数据传输操作中,SI寄存器可以作为源地址寄存器,用于从内存中读取数据。
注意:SI寄存器无法分成两个8位寄存器来使用
DI寄存器·Destination Index
DI寄存器,通常被称为目的索引寄存器。它与SI寄存器类似,主要用于字符串操作和间接寻址。
- 字符串操作:在执行字符串指令时,DI寄存器通常用作目的字符串的偏移量。在执行
MOVSB
等指令时,DS:DI指向要转移的目标位置。 - 间接寻址:DI寄存器可以用于间接寻址模式,其中它作为基地址寄存器,与偏移量结合来形成完整的内存地址。
- 数据传输:在数据传输操作中,DI寄存器可以作为目的地址寄存器,用于将数据写入内存。
注意:DI寄存器也无法分成两个8位寄存器来使用
栈寄存器
和栈相关的寄存器有:SP寄存器·Stack Point、BP寄存器·Base Point、SS寄存器·Stack Segment。
SP寄存器代表堆栈指针,用于指向当前堆栈的顶部;SS寄存器是堆栈段寄存器,用来存储当前堆栈使用的段地址;BP是基址指针,用来指向当前堆栈帧的基地址,可以配合SS寄存器进行寄存器相对寻址。
栈是汇编语言中管理数据的一个重要方法。8086CPU不能直接和内存交换数据,必须要把内存读入寄存器,再送入CPU进行处理。如果我们编写了复杂的程序,寄存器可能会不够用。这时最好的办法就是把寄存器的数据推入栈中保存,执行完对应的过程后再弹出。
和栈相关的寄存器有SS、SP、BP。我们只讨论SS和SP,SS:SP始终指向栈顶元素。一般用push
和pop
来管理栈。
当执行push ax
时,进行操作:
- SP = SP - 2
- 将ax的数据送入SS:SP所指的内存单元
同理执行pop ax
时,进行操作:
- 将SS:SP所指的内存单元送入ax处
- SP = SP + 2
一个常见的考点是,给定栈的范围和SS的值,求SP的值。这里要注意的一点是,SP应该指向栈空间最高地址单元的下一格,具体原因如下图。
给定栈空间10000H~1000FH作为栈,SS=1000H,则SP应为:000FH + 1 = 0010H。
注意,图中AX数据为2266H,AH=22H,AL=66H;故高位内存单元1000FH存放高位字节22H,低位内存单元存放低位字节66H。
段寄存器
段寄存器有DS数据段寄存器·Data Segment、ES附加段寄存器·Extra Segment、CS代码段寄存器·Code Segment和SS堆栈段寄存器·Stack Segment。其中SS寄存器前文已经介绍过。
一般来说,DS用于指定当前的数据段基址。所有的内存操作,均默认以DS寄存器内的数据作为段偏移地址计算内存地址。ES寄存器最初设计用于提供额外的内存寻址能力,但在现代x86架构中,它的用途已经减少。但是在诸如cmpsb
等指令的调用中,还是需要指定ES的值配合SI目的偏移寄存器来使用。
CS常和IP指令指针寄存器·Instruction Point搭配使用。CS和IP是8086CPU中最关键的两个寄存器。在任意时刻,8086CPU将CS:IP指向的内容当做指令执行。
8086CPU的工作流程可以概括如下:
- 从 CS:IP 指向的内存单元读取指令,读取的指令进入指令缓冲器
- IP=IP+所读取指令的长度,从而指向下一条指令
- 执行指令。转到步骤(1),重复这个过程。
注意IP的执行顺序是:先读取指令 -> 缓存指令 -> IP下移至下一条指令 -> 执行指令。尤其是在使用了jmp
等跳转指令时小心,此时IP在执行跳转标号处的指令时会连续移动三次(读入jmp
后指向下一条指令、跳转到标号指令、读入标高处指令并指向下一条指令)。
PSW寄存器·Program Status Word
PSW寄存器即程序状态字寄存器,在8086中,即我们所学的Flag标志寄存器。它的特定位数有对应的用途。
flag 的 1、3、5、12、13、14、15 位在 8086CPU 中没有使用,不具有任何含义。而0、2、4、6、7、8、9、10、11 位都具有特殊的含义。
我们简单介绍CF、PF、ZF、SF、SF、OF、DF等标志位的作用。
标志寄存器 | 作用 |
---|---|
CF(Carry Flag,进位标志) | 用于表示上一次算术运算是否产生了进位或借位。在加法运算中,如果结果超出了寄存器的大小,CF会被设置;在减法运算中,如果结果小于0,CF也会被设置。CF通常用于无符号数运算 |
PF(Parity Flag,奇偶校验标志) | 用于表示上一次操作结果的最低有效字节的奇偶性。如果结果的二进制表示中有偶数个1,则PF被设置为1,表示偶校验;如果有奇数个1,则PF被清除,表示奇校验。 |
ZF(Zero Flag,零标志) | 如果上一次操作的结果为零,则ZF被设置。这个标志位常用于条件跳转指令,以检查操作是否没有产生任何影响。 |
SF(Sign Flag,符号标志) | 用于表示上一次操作结果的符号。在有符号整数运算中,如果结果为负数,则SF被设置;如果结果为正数或零,则SF被清除。 |
OF(Overflow Flag,溢出标志) | 用于表示上一次算术运算是否产生了溢出。在有符号整数运算中,如果结果超出了寄存器能够表示的最大或最小值,OF会被设置。OF专门用于有符号数运算 |
DF(Direction Flag,方向标志) | 用于控制字符串操作指令的方向。当DF被设置时,字符串操作会向内存的低地址方向进行;当DF被清除时,操作会向高地址方向进行。 |
AF(Auxiliary Carry Flag,辅助进位标志) | 用于表示BCD(二进制编码的十进制)算术运算中的辅助进位。在BCD加法运算中,如果从低4位到高4位产生了进位,则AF会被设置。 |
IF(Interrupt Enable Flag,中断使能标志) | 控制CPU是否应该响应外部和内部中断请求。如果IF被设置,CPU将允许中断;如果被清除,则CPU将忽略中断请求。 |
*TF(Trap Flag,陷阱标志) | 当TF标志被设置时,CPU进入单步执行模式。在这种模式下,每执行一条指令后,CPU都会触发一个单步异常(单步陷阱),这通常用于调试目的。不常考察。 |
相应的,也有许多配套的指令和标志寄存器相配合。
比如adc
指令和sbb
指令,和CF标志寄存器相关,分别对应实现8086CPU的借位加和借位减。内容比较冗杂,目前暂且先不介绍。
cmp
指令也很常用,和ZF标志寄存器相关。cmp ax,bx
相当于对两个寄存器的值执行一次不改变寄存器的减法操作,用ZF记录结果的值是否为0。常常和jz
条件转移指令连用。关于条件转移指令,可以参照下文[条件转移指令的介绍](# 条件转移指令)
DF寄存器常和串传送指令相关,用cld
将DF置0,sld
将DF置1。串传送十分重要,常被用来实现新断点例程的安装,参考如下代码段:
assume cs:codesg |
最后,就是pushf
与popf
。这两条指令分别代表将标志寄存器的值入栈和从栈中弹出数据送入标志寄存器内。
内存地址定位与寻址方式
各种寄存器的知识已经介绍完毕,接下来我们就可以来谈谈8086CPU几种不同的寻址方式。
下图总结的十分全面:
寻址方式一共有五种:直接寻址(立即数)、间接寻址(单寄存器)、相对寻址(单寄存器加立即数)、基址变址寻址(寄存器加寄存器)、相对基址变址寻址(寄存器加寄存器加立即数)。
能参与寻址的段寄存器有ds、ss、es;能参与寻址的偏移寄存器有bx、si、di(都默认ds)、bp(默认ss)。
对于8086CPU的指令,可以处理两种尺寸的数据——Byte和Word。为了让机器知道进行字操作还是字节操作,我们需要用操作符X ptr
来指明长度。X
可以是word或者byte。例子如下:
-
mov word ptr ds:[0],1
-
inc byte ptr [bx]
-
div word ptr [bx+8]
ax = (dx * 10000h +ax) / (ds * 16 + bx +8)的商
dx = (dx * 10000h +ax) / (ds * 16 + bx +8)的余数
-
div byte ptr [bx+8]
al = ax / (ds * 16 + bx +8)的商
ah = ax / (ds * 16 + bx +8)的余数
深入转移指令
看到这里,基本的内存访问方法已经差不多搞清楚,接下来就该上点强度了。在高级语言编程时,函数是至关重要的一环。它允许用户开辟一块新的代码段,封装一个功能方便用户调用,大大提高了代码的可读性和封装性。在汇编中,函数过程的调用对应的是转移指令,即可以修改IP,或同时修改CS和IP的指令。
在8086CPU中,转移指令分为以下几类:
- 无条件转移指令(
jmp
) - 条件转移指令(
jz
、jne
等) - 循环指令(
loop
) - 过程(
call
、ret
等) - 中断(
int
、iret
等)
接下来我们来逐一介绍这些转移指令的用法。
修改范围
在进入具体的指令介绍前,我们先了解指令转移行为的类别,这个规律对大部分转移指令都适用:
- 只修改IP,称为段内转移,如:
jmp ax
- 同时修改CS和IP,称为段间转移,如:
jmp 1000:0
段内转移又分为:短转移和近转移。
短转移的IP修改范围为-128~127(IP+8位位移),近转移的修改范围为-32768~32767(IP+16位位移)。短跳转通常用于小范围内的循环或条件语句,近跳转则用于更复杂的流程控制,如跳转到程序的其他部分。
jmp指令
jmp
是最长使用的无条件跳转指令,有以下几种用法:
jmp short 标号
执行段内短跳转。jmp near ptr 标号
执行段内近跳转,是默认的使用方式,等价于jmp 标号
。jmp far ptr 标号
执行段间转移,也称远转移。该指令用标号的段地址和偏移地址修改CS:IP。jmp 16位reg
等价于段内近跳转。jmp word ptr 内存单元地址
等价于执行段内短跳转。jmp dword ptr 内存单元地址
执行段间转移,高地址的字储存转移的目的段地址修改CS,低地址的字储存转移的目的偏移地址修改IP。即CS = 内存单元地址 + 2,IP = 内存单元地址
条件转移指令
条件转移指令常常以字母J开头,比如jcxz
,jz
等。我们对这些繁琐而简短的指令做一个汇总方便记忆
jcxz
(jump if cx zero)指令是有条件转移指令,所有的有条件转移指令都是短转移,在对应的机器码中包含的都是标号的位移而非其目的地址。
jcxz 标号
将检测cx是否为0,如果不为0则跳转至目标标号执行。等同于:if cx==0 {jmp short 标号}
。
可以用jcxz
代替loop
实现循环:
dec cx |
除jcxz
外,下面的指令都是标志寄存器相关的转移指令。
指令 | 含义 | 检测的相关标志位 |
---|---|---|
je/jz | 等于(0)则转移 | zf=1 |
jne | 不等于则转移 | zf=0 |
jb | 低于则转移 | cf=1 |
jnb | 不低于则转移 | cf=0 |
ja | 高于则转移 | cf=0且zf=0 |
jna | 不高于则转移 | cf=1且zf=1 |
jle | 小于等于则转移 | sf=zf |
更多的条件转移指令塞到本章有些过于繁琐,所以我只节选了教材上提到过的条件转移指令,应付考试应该绰绰有余了,其他的资料就留待日后扩展吧。
loop指令
loop
是循环指令,所有的循环指令都是短转移。
调用loop 标号
指令时,会执行以下操作:
-
CX = CX - 1
-
CX==0 ? 执行下一条指令 : jmp 标号
即检查CX的值是否为0,如果为0则退出循环,否则跳转回标号继续循环。
更具体的介绍可以参照cx寄存器的资料。
call与ret
call
和ret
可以视为函数的调用与返回指令。一般的流程是先调用call
,CPU将当前的(此时IP已经指向call
的下一条指令)IP或者CS与IP入栈,然后跳转到目的地址执行,最后再通过ret
或者retf
返回原来的地址。
call
指令和jmp
类似,本质上就是先入栈再跳转,所以用法也类似:
-
call 标号
等价于:push IP
jmp near ptr 标号
-
call far ptr 标号
等价于:push CS
push IP
jmp far ptr 标号
-
call 16位reg
等价于:push IP
jmp 16位reg
-
call word ptr 内存单元地址
等价于:push IP
jmp word ptr 内存单元地址
-
call dword ptr 内存单元地址
等价于:push CS
push IP
jmp dword ptr 内存单元地址
ret
指令有许多变种,依次归纳如下:
-
ret
指令实现近转移,等价于:pop IP
-
retf
指令实现远转移,等价于:pop IP
pop CS
-
iret
指令实现远转移,用于处理中断程序的返回,等价于:pop IP
pop CS
popf
中断
中断是8086CPU的一种能力,这让它能够在执行完当前的指令后,检测到CPU外部发送过来的特殊信息(如断电、键盘输入等),立即去执行其他的指令,而不去接着执行下一条指令。中断分为内中断和外中断两种,重点是内中断;而外中断因为涉及到过多的硬件知识所以简单介绍,只讨论键盘外设的输入及端口。
内中断
一般来说,8086CPU有如下四种中断:
- 除法错误,比如
div 0
,本质上是调用了int 0
号中断 - 单步执行,在debug模式下
- 执行
into
指令 - 执行
int
指令
我们着重介绍第四种情况。
中断的过程
int
指令是如何执行中断程序的呢?
我们前文提到,int
指令也是一种转移指令,那么也就意味着,在执行完对应的中断程序后,CPU还需要跳转回原来的指令继续执行(当然也可能直接终止程序了)。此时的做法和call
类似,在跳转至中断程序前,需要先把此时的CS:IP入栈,然后再进行跳转。
储存好CS:IP后,CPU用8位的中断类型码跳转至中断向量表,找到中断程序的入口地址,再跳转至真正的中断程序执行。中断类型码,即int 类型码
,我们常说的0号中断就是类型码为0。因为中断类型码只有8位,这就意味着中断向量表只能储存256个中断程序。而这其中大部分的中断类型码其实都没有使用,这就给我们拓展CPU的功能留下了空间。
在8086CPU中,中断向量表储存在内存地址0处。从内存0000:0000到0000:03FF共1024个字节中都用来存放中断向量表。在中断向量表中,一个表项存放一个中断向量,也就是中断程序的入口地址。一共占两个字,高地址字存放入口地址的段地址,低地址字存放偏移地址。
加深记忆
1024Byte = 512Word = 256 入口地址 = 256/28个例程 = 8位类型码
对中断程序入口地址的考察也是一个常考点,例题如下:
更简洁的描述中断过程如下:
- 取得中断类型码N
pushf
- TF=0,IF=0(将在下一章讨论)
push CS
push IP
- IP=4N,CS=4N+2
更具体的中断例程的调用不用记忆,比如BIOS和DOS提供的中断程序调用,题目一般会直接给出资料。
下面再给出BIOS提供中断例程的资料拓展,可能会作为材料选择题考察。
在系统板的 ROM 中存放着一套程序,称为 BIOS(基本输入输出系统),BIOS 中主要包含以下几部分内容。
- 硬件系统的检测和初始化程序
- 外部中断和内部中断的中断例程
- 用于对硬件设备进行 I/O 操作的中断例程
- 其他和硬件系统相关的中断例程
CPU在启动时,会先安装BIOS提供的中断例程,再转去启动DOS,具体步骤如下:
- 开机后,CPU 一加电,初始化(CS)=0FFFFH,(IP)=0,自动从 FFFF:0 单元开始执行程序。FFFF:0 处有一条转跳指令,CPU 执行该指令后,转去执行 BIOS 中的硬件系统检测和初始化程序。
- 初始化程序将建立 BIOS 所支持的中断向量,即将 BIOS 提供的中断例程的入口地址登记在中断向量表中。注意,对于 BIOS 所提供的中断例程,只需将入口地址登记在中断向量表中即可,因为它们是固化到 ROM 中的程序,一直在内存中存在。
- 硬件系统检测和初始化完成后,调用int 19h 进行操作系统的引导。从此将计算机交由操作系统控制。
- DOS 启动后,除完成其他工作外,还将它所提供的中断例程装入内存,并建立相应的中断向量。
外中断
外中断即是由外部设备输入CPU产生的中断信息,我们先简单的介绍一下端口的概念,介绍CPU与外设的基本通信方式,再讨论外中断。
端口
CPU可以直接读写以下3个地方的数据:
- CPU内部的寄存器
- 内存单元
- 端口
端口实际上是一组接口芯片,它们既可以控制接口卡进行工作,还可以利用芯片自带的可供CPU读写的寄存器储存CPU发来的信息。从CPU的角度来讲,它都把这些寄存器当做端口进行统一编址,从而建立一个统一的端口地址空间,每一个端口空间在地址空间中都有一个地址,这样CPU就可以通过访问地址的方式访问端口从而和外设建立起通信。
因为端口所在的芯片和CPU通过总线相连,所以端口地址和内存地址一样,通过地址总线来传送。最多可以定位64kb个不同的端口,即端口的范围为0~65535。
在汇编中,则是通过in
和out
指令来调用端口。用法如下:
;对0~255以内的端口进行读写时 |
注意,在in
和out
指令中,只能用ax或al来存放从端口中读入的数据或者发送到端口的数据。访问8位端口时用al,16位端口用ax。
外中断响应信息
介绍完端口通信的内容,我们就要引入对于外中断来说一个重要的概念:可屏蔽中断与不可屏蔽中断。
可屏蔽中断
可屏蔽中断是 CPU 可以不响应的外中断。CPU 是否响应可屏蔽中断,要看标志寄存器的IF位的设置。当 CPU 检测到可屏蔽中断信息时,如果 IF=1,则 CPU 在执行完当前指令后响应中断,引发中断过程;如果IF=0,则不响应可屏蔽中断。
过程如下:
- 取中断类型码n
pushf
,IF=0,TF=0push CS
,push IP
- IP = 4 * n,CS = 4 * n + 2
可屏蔽中断通常使用sti
和cli
指令来处理。
sti
,设置标志寄存器IF=1,此时可以响应可屏蔽外中断cli
,设置标志寄存器IF=0,此时禁止响应所有的可屏蔽中断
可屏蔽中断所引发的中断过程,除在第1步的实现上有所不同外,基本上和内中断的中断过程相同。因为可屏蔽中断信息来自于 CPU 外部,中断类型码是通过数据总线送入CPU 的;而内中断的中断类型码是在 CPU 内部产生的。
现在,我们可以解释中断过程中将IF置为0的原因了。将IF置0的原因就是,在进入中断处理程序后,禁止其他的可屏蔽中断。
常见的考点是,在考察安装新的键盘int 9h
中断时,在处理地址时要先用cli
关闭相应可屏蔽中断,在地址更改完毕后再用sti
恢复响应。这是为了防止在设置int 9h
中断例程地址时发生键盘中断,导致CPU转去一个错误的地址执行。
不可屏蔽中断
不可屏蔽中断是 CPU 必须响应的外中断。当 CPU 检测到不可屏蔽中断信息时,则在执行完当前指令后,立即响应,引发中断过程。比如电脑掉电就是一个不可屏蔽中断。
对于 8086CPU,不可屏蔽中断的中断类型码固定为 2,所以中断过程中,不需要取中断类型码。则不可屏蔽中断的中断过程为:
pushf
,IF=0,TF=0push CS
,push IP
- IP = 4 * 2 = 8,CS = 4 * 2 + 2 = 0AH
我们主要讨论可屏蔽中断,不可屏蔽中断仅做了解就好。
其他
因为是理论课总结,考虑到有同学没有选修实验课,所以这里减少了有关实验部分的知识点。
关于直接定址表和使用BIOS进行键盘输入与磁盘读写的内容,虽然在实验部分比较重要,但是在理论上考察却很容易理解或者不会考察,所以这里没有总结。
那么,本总结就到此为止啦,祝大家汇编考试分数++
- 将小写字母的ASCII码减去20H可以得到对应的大写字母ASCII码,在处理大小写转换时很常用。