Typist : Akame Qixisi / Excel Bloonow

在我学习汇编语言(基于8086)的过程中,遇到过一些想要某些操作却不知道指令的情况,所以在这里统一记录一下。如有错误或不同观点欢迎批评指出。

8086/8088指令系统

8086/8088指令系统的指令分为7类,即数据传送、算术运算、逻辑操作、程序控制、数据串操作、处理器控制、输入输出。在学习指令系统时,应该从4个方面掌握这个指令,如下:

  1. 掌握指令的功能:该指令能够实现何种操作,通常指令助记符就是指令功能的英文单词或器缩写形式。
  2. 分析指令支持的寻址方式:该指令中的操作数可以采用何种寻址方式。
  3. 清楚指令对标志位的影响:该指令执行后是否对各个标志位有影响,以及如何影响。
  4. 其他特征:如指令执行时的约定设置、必须预置的参数、隐含使用的寄存器等。

数据传送类指令

实现数据从一个位置到另一个位置的移动,如执行寄存器与寄存器之间、寄存器与主存单元之间的字或字节的多种传送操作。

1. 数据传送指令 mov

mov oprd1, oprd2 ; oprd1 = oprd2
  • 该指令将一个8位或16位的源操作数(字或字节)送到目的操作数中。本指令不影响状态标志位。
  • oprd1,目的操纵数,可以是寄存器、存储器、累加器、标号。
  • oprd2,源操作数,可以是寄存器、存储器、累加器、立即数、标号。
  • 立即数只能作为源操作数,不能作为目标操作数,立即数也不能传送至段寄存器。
  • 存储器与存储器之间不能进行数据直接传送。若要实现存储单元之间的数据传送,可以借助于通用寄存器作为中介来进行。
  • 指令指针IP不参加数的传送;代码段寄存器CS可以作为源操作数参加传送,但不能作为目的操作数参加传送。
  • 源操作数和目的操纵数的类型应一致,可以使用byte ptrword ptr指定其后跟的是一个字节还是一个字,告诉编译程序按什么类型处理,生成相应的指令代码。如两侧都是内存单元时,或者使用标号label等无法确定具体位数时。其中ptr称为指针操作符,作用是将后跟的标号或者内存单元定义为新的变量类型,如byte或word,这个变量的起始地址没有改变。

2. 数据交换指令 xchg

xchg oprd1, oprd2
  • 该指令把操作数oprd1与操作数oprd2交换。本指令不影响状态标志位。

  • oprd1位目标操作数,oprd2为源操作数,可为通用寄存器、存储器。

  • xchg指令不支持两个存储器单元之间直接数据交换,但通过中间寄存器,可以很容易的实现两个存储器操作数的交换。

  • 段寄存器中的内容不能用xchg来交换。

3. 换码指令 xlat

xlat ; (AL) = (DS:[(BX)+(AL)])
  • 该指令把待查表格的一个字节内容送到AL中。执行该指令前,应先把TABLE表格的地址值送至BX寄存器中,然后将待查字节在表格中距离表格首地址的偏移地址送AL,然后使用xlat指令将对应地址上的值取到AL中。段地址是DS提供的。本指令不影响状态标志位。
  • 使用前首先在主存中建立一个字节表格(即DS中一段连续的存储空间),表格的内容是要转换成的目标代码。xlat指令中没有显示指明操作数,而是默认使用bx和al寄存器,这种采用默认操作数的方法称为隐含寻址方式。
  • 由于AL的内容实际上是距离表格首地址的移位量,只有8位,所以表格的最大长度为256;超过256的表格需要采用修改BX和AL的方法才能转换。
  • 换码指令常用于将一种代码转换为另一种代码,如扫描码转为ASCII码,数字0到9转换为七段显示码等。

4. 堆栈操作指令

push oprd
  • 该指令将16位(字)操作数oprd压栈,oprd可以是寄存器或者存储器操作数。本指令不影响状态标志位。
  • push的操作过程是:先修改堆栈指针SP(入栈时为自动减2h),然后将指定的操作数送入新的栈顶位置。随着入栈内容的增加,堆栈就扩展,SP值减少,但每次操作完,SP总是指向堆栈的顶部。
  • 实际上,诸如push ax压栈时,实际上是先SP减1,送AH,再SP减1,送AL。
pop oprd
  • 该指令将栈顶的16为(字)弹出到oprd操作数,oprd可以是寄存器或存储器操作数。本指令不影响状态标志位。
  • 它与入栈的操作相反,是先弹出栈顶的数据,然后再修改指针SP的内容。

5. 标志传送指令

lahf
  • 取FLAGS标志寄存器低8位至AH中。该指令不影响FLAGS的原来内容,AH只是复制了原FLAGS的低8位内容。
sahf
  • 将AH存至FLAGS标志寄存器的低8位。本指令将用AH的内容改写FLAGS中的SF、ZF、AF、PF和CF标志,从而改变原来的标志位。
pushf
  • 本指令可以把FLAGS的内容保存到堆栈中去。
  • 在子程序调用和中断服务程序中,往往用pushf指令保护FLAGS的内容,用popf指令恢复保护的FLAGS中的内容。
popf
  • 从堆栈中弹出一个数据字送至FLAGS中。

6. 地址传送指令

地址传送指令将存储器的逻辑地址送至指定的寄存器。

lea oprd1, oprd2 ; mov oprd1, offset oprd2
  • 该指令将源操作数oprd2给出的有效地址(段内偏移量)传送到指定的寄存器中。本指令对标志寄存器无影响。
  • oprd1,目标操作数,可以位任意一个16位的通用寄存器。
  • oprd2,源操作数,可为变量名、标号、地址表达式。
  • 如果要将一个存储器变量的地址取至某一个寄存器中,也可以通过offset label来获取一个标号label的段内偏移量。
lds oprd1, oprd2
les oprd1, oprd2
  • 从存储器取出段地址和偏移地址放到oprd1所指定的16位寄存器中。本指令不影响标志寄存器。
  • oprd1,目标操作数,可以为任意一个16为寄存器。
  • oprd2,源操作数。可以为一个内存单元地址变量,该地址指定了主存的连续4个字节作为逻辑地址,低2个字节存放到oprd1中,高2各字节存放到DS或ES中(由指令确定)。可以为一个label标号,使用的是由DS:label指定的地址处的4个连续的4个字节作为逻辑地址。
offset label
seg label
  • 分别取标号的偏移地址和段地址。

算术运算类指令

算术运算类指令用来执行二进制及十进制的算术运算,主要包括加减乘除指令。二进制数运算分为带符号数运算和不带符号数运算。十进制数用BCD码表示,又分为非压缩的BCD码和压缩的BCD码两种形式。

算术运算类指令会根据运算结果影响状态标志位,有时要利用某些标志才能得到正确的结果。该类指令主要影响6个标志位,即CF、AF、SF、ZF、PF、OF。

1. 加法指令

add oprd1, oprd2 ; oprd1 = oprd1 + oprd2
  • 该指令实现字或字节的加法运算,适用于无符号数及带符号数的8位或16位加法运算。对CF、AF、SF、ZF、PF、OF结果标志都有影响。
  • oprd1,目标操作数,可以是任意一个通用寄存器,也可以是任意一个存储器操作数。在执行add之前,oprd1中的内容为一个加数,待add指令执行后,oprd1中为加法运算的结果即和。
  • oprd2,源操作数,可以是任意一个通用寄存器或存储器操作数,也可以是立即数。
  • oprd1和oprd2均为寄存器是允许的,一个为寄存器另一个为存储器也是允许的,但不允许两个都是存储器操作数。
adc oprd1, oprd2 ; oprd1 = oprd1 + oprd2 + CF
  • 带进位的加法指令,适用于无符号数及带符号数的8位或16位加法运算。对标志位的影响同add指令。
  • oprd1和oprd2两个操作数与指令add中的含义一样。
inc oprd ; oprd = oprd + 1
  • 加一指令,对给定的寄存器或存储单元内容加1后,再送回该操作数,可以实现字节加1或字加1。该指令不影响CF标志位,影响其他标志位。
  • oprd为寄存器或存储器操作数,寄存器不能是段寄存器。
  • 在循环程序中,常用该指令对地址指针和循环计数值进行修改。

2. 减法指令

sub oprd1, oprd2 ; oprd1 = oprd1 - oprd2
  • 该指令实现两个操作数的减法操作,操作数可为8位或16位的无符号数或带符号数。对标志位的影响同add指令。
  • 注意立即数不能用于目的操作数,两个存储器操作数之间不能直接相减。
sbb oprd1, oprd2 ; oprd1 = oprd1 - oprd2 - CF
  • 带进位的减法指令,操作数可为8位或16位的无符号数或带符号数。对标志位的影响同sub指令。
dec oprd ; oprd = oprd - 1
  • 减一指令,对给定的寄存器或存储单元内容减1后,再送回该操作数,可以实现字节减1或字减1。该指令不影响CF标志位,影响其他标志位。
  • oprd为寄存器或存储器操作数,寄存器不能是段寄存器。
  • 在循环程序中,常用该指令对地址指针和循环计数值进行修改。
neg oprd
  • 取补指令,该指令对操作数执行求补运算,即用basen减去操作数,然后将结果返回操作数。二进制的求补运算也可以表达成,将操作数按位取反后加1。
  • oprd为任意通用寄存器或存储器操作数。
  • neg指令对标志状态位的影响与用0(如果当前位不够减,在最高位的前一位补1,则用basen减就相当于用0减)做减法的sub指令一样。
cmp oprd1, oprd2
  • 比较指令,该指令该指令用于改变标志位,它对标志位的影响同sub指令,完成的操作与sub指令类似,唯一的区别是不将oprd1-oprd2的结果送回oprd1中,而只是比较。
  • oprd1和oprd2可以为任意通用寄存器或存储器操作数,但两者不同时为存储器操作数,立即数可用于做源操作数oprd2。

3. 乘法指令

相同的二进制数看作无符号数还是有符号数相乘,采用mul或imul指令,其运算结果时不相同的。

mul oprd ; 16位 = 8位 * 8位:(AX) = (AL) * oprd; 32位 = 16位 * 16位:(DX)(AX) = (AX) * oprd
  • 无符号数乘法指令,该指令可用于无符号数的8位乘法或16位乘法。该指令影响CF、OF标志位。
  • oprd,源操作数,即乘数。可以为通用寄存器或存储器操作数,根据它的位数确定是8位乘法还是16位乘法。
  • 目的操作数是隐含的,即被乘数总是指定为累加器AX或AL的内容。
    • 8位字节乘法时,AL为被乘数,16位积存放于AX中;当结果的高位字节(AH)≠0时,则CF=OF=1。
    • 16位字乘法时,AX为被乘数,32位积存于DX和AX中;当结果的高位字(DX)≠0时,则CF=OF=1。
imul oprd
  • 带符号数乘法指令,该指令的功能是完成两个带符号数的相乘。该指令影响CF、OF标志位。
  • oprd,源操作数,即乘数。可以为通用寄存器或存储器操作数。
  • 隐含操作数的定义于mul指令相同。

4. 除法指令

除法指令div和idiv不产生有效的标志位,但是却可能产生溢出。当被除数远大于除数时,或除数位0时,所得的商就有可能超出它所能表达的范围。

符号扩展是用一个操作数的符号位(即最高位)形成另一个高位操作数,它的各位全是0(正数)或全是1(负数)。符号扩展指令可用来将字节转换为字,字转换为双字;有符号数通过符号扩展加长了位数,但数据的大小没有改变。符号扩展指令常用来获得有符号数除法指令所需的被除数;对于无符号数应该采用直接使用高8位或高16位清0的方法,获得被长的被除数,即0位扩展。

div oprd ; 8位 = 16位 / 8位:(AL) = (AX) / oprd, (AH) = (AX) % oprd; 16位 = 32位 / 16位:(AX) = (DX)(AX) / oprd, (DX) = (DX)(AX) % oprd
  • 无符号数除法指令,该指令的功能时实现两个8位或16位无符号数二进制除法运算。
  • oprd,源操作数,存放的是除数。可以为通用寄存器或存储器操作数,根据它的位数确定是16位除法还是32位除法。
  • 目的操作数是隐含的,即被除数总是指定为AX或DX的内容。
    • 16位字除法时,AX为被除数,8位商存放于AL中,8位余数存放于AH中。
    • 32位双字除法时,DX和AX为被除数,16位商存放于AX中,16位余数存放于DX中。
idiv oprd
  • 带符号数的除法指令,该指令的功能是实现两个带符号数的二进制除法运算,余数的符号与被除数符号相同。
  • oprd,源操作数,可以为通用寄存器或存储器操作数。
  • 隐含操作数的定义与div指令相同。
cbw
  • 有符号数的字节扩展指令,该指令的功能是将字节扩展为字,即把AL寄存器的符号位扩展到AH中。两个字节相除时,先使用本指令形成一个两字节的被除数。该指令不影响标志位。
cwd
  • 有符号数的字扩展指令,该指令的功能是将字扩展为双字长,即把AX寄存器的符号位扩展到DX中。两个字相除时,先使用本指令形成一个两字长的被除数。

5. 十进制调整指令

十进制数在计算机中也要用二进制编码表示即BCD码,8086/8088支持压缩BCD码和非压缩BCD码。

  • 压缩BCD码是通常的8421码,它用4个二进制位表示一个进制数,一个字节可以表示两位十进制数,即00~99。
  • 非压缩BCD码用8个二进制位表示一个十进制数,一个字节可以表示一位十进制数,即0~9。非压缩BCD码的高4位通常默认为0。ASCII码中0~9的编码是30H~39H,所以0~9的ASCII码(高4位变为0)就可以认为是非压缩的BCD码。由于只要在调整后的结果中加上30H就成为十进制数位的ASCII码,因此这组针对非压缩BCD调整的指令实际上也是针对ASCII码的调整指令。

在进行十进制数的算术运算时,应该分为两步进行:先按二进制数运算规则进行运算,得到中间结果;再用十进制调整指令对中间结果进行修正,得到正确结果。

需要修正的原因是,按照二进制进行运算没有错误,但如用4位二进制按照压缩BCD码表示十进制,十进制实际上是逢十进一,而4位二进制数是逢0AH进一。这就会出现问题,即目标结果BCD码的二进制串,与直接按二进制数运算得来的二进制串不一致,需要进行调整。需要用到AF标志位。

结论:加法运算后,低4位大于9时,需要做加06H处理;高4位大于9时,需要做加60H处理;减法则反之减去。

daa
  • 对压缩BCD码加法运算进行校正。一般在add指令把两个压缩BCD相加之后,紧接着用一条daa指令对AL内容加以校正,在AL中可以得到正确的结果。
das
  • 对压缩BCD码减法运算进行校正。一般在sub指令把两个压缩BCD相减之后,紧接着用一条das指令对AL内容加以校正,在AL中可以得到正确的结果。
aaa
  • 对非压缩BCD码加法运算进行校正。一般在add指令把两个非压缩BCD相加之后,紧接着用一条aaa指令对AL中的内容加以校正,在AX中可以得到正确结果。
aas
  • 对非压缩BCD码减法运算进行校正。一般在sub指令把两个非压缩BCD相减之后,紧接着用一条aas指令对AL中的内容加以校正,在AX中可以得到正确结果。
aam
  • 对非压缩BCD码乘法运算进行校正。一般在mul指令把两个非压缩BCD(要求高4位为0)相乘之后,紧接着用一条aam指令对AL中的内容加以校正,在AX中可以得到正确结果,商放在AH中,余数放在AL中。
aad
  • 对非压缩BCD码除法运算进行校正。它与其他校正指令不同,如果被除数是存放在AH和AL中的两位非压缩BCD(要求高4位为0),除数是一个非压缩BCD数(高4位为0),要先用aad指令把AX中的被除数调整为二进制数,并存放在AL寄存器中。之后才能调用div指令。

逻辑操作类指令

逻辑操作类指令是按位操作指令,可以对8位或16位的寄存器或存储器单元的内容按位操作。

1. 逻辑运算指令

and oprd1, oprd2
  • 该指令实现对两个操作数按位进行逻辑与的运算,结果送至目的操作数,可进行字节或字的与运算。该指令影响标志位PF、SF、ZF,是CF=0,OF=0。
  • oprd1,目的操作数,可以为任意通用寄存器或存储器操作数。两个操作数不能同时位存储器寻址方式。
  • oprd2,源操作数,可以为任意通用寄存器或存储器操作数,也可以是立即数。
  • 本指令主要用于修改操作数或置某些位为0。
or oprd1, oprd2
  • 该指令实现对两个操作数按位进行逻辑或的运算,结果送至目的操作数,可进行字节或字的或运算。对标志位的影响同and指令。
  • oprd1,目的操作数,可以为任意通用寄存器或存储器操作数。两个操作数不能同时位存储器寻址方式。
  • oprd2,源操作数,可以为任意通用寄存器或存储器操作数,也可以是立即数。
  • 本指令主要用于置位某些位为1,而不影响其他位,只需要将要置位的位同1相或,保存不变的位同0相或。
not oprd
  • 该指令实现对操作数的按位求反运算,结果送回原操作数,可进行字节或字的求反运算。不影响标志位。
  • oprd可为任意通用寄存器或存储器操作数。
xor oprd1, oprd2
  • 该指令实现两个操作数进行按位异或运算,结果送至目的操作数,可进行字节或字的或运算。对标志位的影响同and指令。
  • oprd1,目的操作数,可以为任意通用寄存器或存储器操作数。两个操作数不能同时位存储器寻址方式。
  • oprd2,源操作数,可以为任意通用寄存器或存储器操作数,也可以是立即数。
  • 本指令主要用于求反某些位,而不影响其他位,要求反的位同1异或,维持不变的位同0异或。
test oprd1, oprd2
  • 也是对oprd1和oprd2进行按位逻辑与运算,操作数的含义也同and,对标志位的影响也同and。
  • 唯一不同的是该指令不会把结果写回oprd1目的操作数,仅是为了在逻辑与操作后,对标志位进行重置。
  • 该指令通常用于检测一些条件是否满足,但又不希望改变原操作数的情况。这条指令之后,一般都是条件转移指令,目的是利用测试条件转向不同的程序段。

2. 逻辑移位指令

shl oprd1, count
  • 逻辑左移指令,该指令的功能是对8位或16位目的操作数左移count次,每次一位,每次移位时最高移位入标志位CF中,最低位补0。该指令对OF、PF、SF、ZF、CF有影响。
  • oprd1,目的操作数,可以是任意通用寄存器或存储器操作数。
  • count,代表移位的次数(或位数),移位一次,count=1,移位多于一次时,CL=count指定移位次数。
shr oprd1, count
  • 逻辑右移指令,该指令的功能是对8位或16位目的操作数右移count次,每次一位,每次移位时最低移位入标志位CF中,最高位补0。
  • oprd1和count的含义同shl指令。
sal oprd1, count
  • 算术左移指令,该指令的功能是对8位或16位目的操作数左移count次,每次一位,每次移位时最高移位入标志位CF中,最低位补0,这些功能同指令shl一样。而且,如果sal将oprd1的最高移位至CF时改变了CF原来的值,则溢出标志位OF=1,表示移位前后的操作数不再是倍增关系。因而sal可用于带符号数的倍增运算,shl只能用于无符号数的倍增运算。
  • oprd1和count的含义同指令shl中的含义。
sar oprd1, count
  • 算术右移指令,该指令的功能是对8位或16位目的操作数右移count次,每次一位,每次移位时最低移位入标志位CF中,最高位(符号位)保持不变。
  • oprd1和count中的含义同指令shl中的含义。
  • 该指令通常用于对带符号数的减半运算中。

3. 循环移位指令

循环移位指令实现的是操作数首尾相连的移位操作,要求从一端移除出的数据返回到另一端形成循环。这类指令只影响CF和OF。按进位标志CF是否参加循环移位,又可分为带CF的和不带CF的,每类都有可左移或右移。OF取决于位移一次后符号位是否改变,如果改变则OF=1。由于是循环移位,对字节连续移动8次,对字连续移动16次就会变为原操作数。

rol oprd1, count
ror oprd1, count
  • 不带进位CF的循环移位指令。左移时移出的最高位,右移时移出的最低位,会放入CF中。
rcl oprd1, count
rcr oprd1, count
  • 带进位CF的循环移位指令。左移时移出的最高位放入CF中,CF放入最低位中;右移时移出的最低位放入CF中,CF放入最高位中。

程序控制类指令

利用程序控制指令,可以实现分支、循环、子程序等程序结构。

1. 无条件转移指令

jmp oprd
  • 无条件转移指令,默认是段内转移。
  • oprd,源操作数,可以为通用寄存器。它的功能是用寄存器的内容修改IP,即(IP) = (16位寄存器),它是段内转移。使用寄存器在程序中是可变的,更灵活。值得注意的是,jmp 2000:0000之类用立即数给出的形式,只能够用在debug环境下,如果出现在源程序中,编译器是无法识别和编译的。
jmp short label
jmp near ptr label
jmp far ptr label
  • 如果使用jmp label,有以上几种。在段内转移的机器指令中,包含的是跳转到目标指令的相对位置,而不是转移的目标地址。位移=目标地址-jmp指令的下条指令的起始地址,在编译时算出。
  • jmp short label,段内短转移,IP修改范围为-128~127一个字节。功能是(IP) = (IP) + 8位位移,关键字short用来指明位移是8位,用补码表示。
  • jmp near ptr label,段内近转移,IP修改范围为-32768~32767两个字节。功能是(IP) = (IP) + 16位位移,关键字near ptr用来指明位移是16位,用补码表示。
  • jmp far ptr label,段间转移(远转移),同时修改CS和IP。在它的机器指令中包含的直接是目标指令的段地址CS和偏移地址IP。
jmp word ptr oprd
jmp dword ptr oprd
  • 如果使用内存地址单元上的值来给出转移地址,有以上几种。内存单元的地址可以由多种寻址方式给出。
  • jmp word ptr oprd,段内转移,从内存单元地址上取一个字,作为转移的偏移地址。
  • jmp dword ptr oprd,段间转移,从内存单元地址上取两个字,高地址的字表示要转移目标的段地址,低地址的字表示偏移地址。

2. 条件转移指令

通常在转移之前先调用如cmp oper1, oper2之类的可以影响PSW的指令,然后调用以j开头的jxxx类指令。需要知道的是:j = Jump、e = Equal、n = Not、b = Below、a = Above、l = Less、g = Greater、s = Sign、c = Carry、p = Parity、o = Overflow、z = Zero。它们都可以跟在 j 之后,也可以一起组合跟在 j 之后。需要注意的是,a 和 b 是对整个机器位比较,即无符号数;而 l 和 g 是将整个机器数看作有符号数,进行比较;它们的测试条件是不同的。

jxxx oprd
  • 条件转移指令的操作数必须是一个短标号,也就是说所有的条件转移指令都是两字节指令,转移指令的下一条指令到目标指令之间的距离必须为-128~127之间。如果指令规定的条件满足,则将这个位移量加到IP寄存器上,即条件转移本质上是修改IP的值。
jcxz oprd
  • 当(cx) = 0时,则转移到标号处执行;否则cx不为0,则什么也不做,程序向下执行。使用jcxz不仅仅可以处理循环。

根据单个标志位状态判断的条件转移指令,如下表:

助记符 指令名称 测试条件
je、jz 等于、零转移 ZF=1
jne、jnz 不等于、非零转移 ZF=0
js 负转移 SF=1
jns 正转移 SF=0
jp、jpe 偶数个1转移 PF=1
jnp、jpo 奇数个1转移 PF=0
jo 溢出转移 OF=1
jno 不溢出转移 OF=0
jc 进位转移 CF=1
jnc 不进位转移 CF=0

用于无符号数的比较跳转指令,如下表:

助记符 指令名称 测试条件
jb、jnae 低于、不高于等于 CF=1
jnb、jae 不低于、高于等于 CF=0
ja、jnbe 高于、不低于等于 CF=1 且 ZF=0
jna、jbe 不高于、低于等于 CF=0 或 ZF=1

用于有符号数的比较跳转指令,如下表:

助记符 指令名称 测试条件
jg、jnle 大于、不小于等于 SF=OF 且 ZF=0
jng、jle 不大于、小于等于 SF != OF 或 ZF=1
jl 、 jnge 小于、不大于等于 SF != OF 且ZF=0
jnl 、 jge 不小于、大于等于 SF = OF

3. 循环控制指令

循环流程的条件一般时循环计算,指令约定用CX寄存器作为计数器,它的循环体至少执行一次。这类指令属于段内短转移,目标地址必须在距本指令-128~127个字节的范围内。

loop label
  • 先将(CX)减一,再判断(CX)是否为0,如果(CX)≠0时,则转移到标号处执行;直到(CX)=0,跳出循环继续执行后续程序。该指令不影响标志位。
loopz label
loope label
  • 先将(CX)减一,再判断(CX)是否为0,如果(CX)≠0且ZF=1时,则转移到标号处执行;直到(CX)=0或ZF≠1时,跳出循环继续执行后续程序。该指令不影响标志位。
loopnz label
loopne label
  • 先将(CX)减一,再判断(CX)是否为0,如果(CX)≠0且ZF=0时,则转移到标号处执行;直到(CX)=0或ZF≠0时,跳出循环继续执行后续程序。该指令不影响标志位。

4. 过程调用和返回指令

相当于子程序或者说函数的调用与转移,实质上是修改 IP 寄存器甚至 CS 寄存器的值。不要忘了为call和ret指定栈段。call和ret指令不影响标志位。

call oprd
  • 段内间接调用,过程与调用指令同处在一个代码段内。oprd为16为通用寄存器或存储器操作数或label。
  • 本指令执行时,先将IP的内容入栈保护(SP减2),然后从由oprd指定的寄存器或存储器中取出一个字,即目的地址在段内偏移量,送入IP中,从而实现过程调用。
call near ptr label
  • 段内直接调用,过程与调用指令同处在一个代码段内。
  • 本指令执行时,先将IP的内容入栈保护(SP减2),然后将指令代码中给出的目标地址的段内偏移量送入IP,从而实现过程调用,将程序转至过程入口。
call word ptr oprd
  • 段内调用,也可以使用存储器操作数指定目标地址。
  • 本指令执行时,先将IP的内容入栈保护。然后从由oprd指定的存储器中取出一个字,即目的地址在段内偏移量,送入IP中,从而实现过程调用。
call far ptr label
  • 段间调用,过程与调用指令可以在不同的代码段中。
  • 本指令执行时,应先将CS压栈,再将IP压栈(SP减4),然后将far类型的过程名所在的段地址和段内偏移地址送入CS及IP,从而实现过程调用。
call dword ptr oprd
  • 段间调用,也可以使用存储器操作数指定目标地址。
  • 本指令执行时,先将SP再将IP的内容入栈保护。然后从由oprd指定的存储器中取出两个字,高地址字作为段地址送入CS,低地址的字作为段内偏移量送入IP,从而实现过程调用。
ret
  • 段内返回指令,当调用的过程结束后实现从过程返回至原调用程序的下一条指令。
  • 本指令执行时,实际上是从栈中取栈顶的数据,恢复IP,因而可以没有与它匹配的call指令,但也要注意是否对栈进行了操作导致栈顶不是IP从而返回错误。
retf
  • 段间返回指令,本指令执行时,实际上是先从栈顶取一个字送入IP、再取一个字送入CS。

5. 中断指令

处理器终止当前程序的运行,转去执行中断处理程序的情况称为“中断”,中断子程序执行完后返回原来程序的断点。8086/8088具有很强的中断系统,可以处理256个不同方式的中断,每一个中断赋予一个中断向量码,CPU根据中断向量码来识别不同的中断源。

8086/8088内部中断源有除法错中断、单步中断、断点中断、溢出中断、用户自定义的软中断5中类型;外部中断是指来自CPU之外的原因引起的程序中断,分为可屏蔽中断和非屏蔽中断2种类型。

into
  • 溢出中断指令,该指令检测OF标志位,当OF=1发生溢出时,立即产生一个中断类型4的中断;当OF=0时,本指令不起作用。
int n
  • 软中断指令,本指令将产生一个软中断,把控制转向一个类型号为n的软中断,该中断处理程序的入口地址在中断向量表的n*4的地址处的两个存储字(4个字节单元)中。
iret
  • 中断返回指令,用于中断处理程序中,从中断程序的断点处返回,继续执行原程序。本指令影响所有标志位。
  • 无论是软中断,还是硬中断,本指令均可使其返回到中断程序的断点处继续执行原程序。

串操作类指令

数据串可以时字节串,也可以是字串,数据串只能放在存储器中。对数据串进行处理时,可以只操作一个串也可以操作两个串,根据数据串中数据流动的方向,可以分为源数据串和目的数据串。

在串操作指令中,源数据串用寄存器SI寻址,默认在数据段DS中,允许段超越;目的数据串用寄存器DI寻址,默认在附加段ES中,不允许段超越。每执行一次串操作指令,地址指针SI、DI都会自动修改:对于字节串会±1,对于字串会±2;增加还是减少取决于方向标志DF。

cld
  • 清楚标志位,使DF=0(默认),此时地址指针向高地址变化,即增加。
std
  • 设置标志位,使DF=1,此时地址指针向低地址变化,即减少。

1. 串传送指令

movs oprd1, oprd2
movsb   ; byte, ES:[DI] = DS:[SI], (SI) = (SI) ± 1, (DI) = (DI) ± 1
movsw   ; word, ES:[DI] = DS:[SI], (SI) = (SI) ± 2, (DI) = (DI) ± 2
  • 串传送指令movs,将数据段主存单元的1个字节或字,传送到附加段的主存单元中。定义数据串时,要求原串和目的串类型一致,并以其区别是字节或字操作。该指令不影响标志位。
  • 指令movsb和movsw,分别对字节串和字串操作。若DF=0,则从当前位置向后;若DF=1,则从当前位置向前。

2. 串比较指令

cmps oprd1, oprd2
cmpsb
cmpsw
  • 串比较指令cmps,对一个字节或字进行比较,比较结果送至标志位,而不改变操作数本身。该指令影响标志位AF、CF、OF、SF、PF、ZF。
  • 指令cmps,可用来检查两个字符串是否相同,可以使用循环控制方法对整个字符串进行比较。
  • 指令cmpsb和cmpsw,分别比较一个字节或一个字。要比较的字符将由SI和DI指定,同时DI、SI将根据DF自动调整。

3. 串扫描指令

scas oprd
scasb
scasw
  • 串扫描指令scas,将AL或AX中的内容与oprd指定的存储器单元中的数据进行比较,根据比较结果设置标志位,但不改变操作数本身。该指令影响标志位AF、CF、OF、SF、PF、ZF。
  • 指令scas,可查找字符串中一个关键字,只需要在本指令执行前,把关键字放入AL或AX中,用重复前缀可在整串中查找。
  • 指令scasw和scasw,分别将ES:[DI]指定的一个字节或字的数据,与AL或AX寄存器中的数据比较,同时DI将根据DF自动调整。

4. 串读取指令

lods oprd
lodsb
lodsw
  • 串读取指令lods,把由oprd指定的存储器单元中的数据读入到AL或AX中。该指令不影响标志位。
  • 指令lodsb和lodsw,分别将DS:[SI]指定的一个字节或一个字的存储器单元数据,送入到AL或AX寄存器中,同时SI将根据DF自动调整。

5. 字符串存储指令

stos oprd
stosb
stosw
  • 字符串存储指令stos,把用AL或AX中的数据内容送入由oprd指定的存储器单元中。该指令不影响标志位。
  • 指令stosb和stosw,分别将AL或AX中的数据内容,送入到DS:[DI]指定的存储器单元数据中,同时DI将根据DF自动调整。

6. 重复前缀指令

rep  command                     ; cx≠0,重复执行command
repz command    repe command    ; cx≠0 且 ZF=1,重复执行command
repnz command   repne command   ; cx≠0 且 ZF=0,重复执行command
  • 在串操作指令前加上重复前缀,可以对数据串进行重复执行command指令,重复的次数存放在cx寄存器中。
  • 指令rep与movs或stos串操作指令结合使用,完成一组数据的传送或建立一组相同数据的字符串。
  • 指令repz/repe与cmps串操作指令结合使用,完成两组数据串的比较。当两数据相同且串未结束时,重复执行串操作指令。它可以用来判断两数据串是否相同或查找第一个不相同的位置。
  • 指令repnz/repne与cmps串操作指令结合使用,当两数据不相同且串未结束时,重复执行串操作指令。它可以在两数据串中查找第一个相同数据的位置。
  • 指令repz/repe与scas串操作指令结合使用,完成在一个字符串中扫描一个关键字。当数据串中与关键字相同且串未结束时,重复执行串操作指令。它可以用于在一个数据串中找出第一个与关键字不匹配的位置。
  • 指令repnz/repne与scas串操作指令结合使用,完成在一个字符串中匹配一个关键字。当数据串中与关键字不相同且串未结束时,重复执行串操作指令。它用于在一个数据串中找出第一个与关键字匹配的位置。

处理器控制类指令

处理器控制指令用于控制CPU的动作,修改标志寄存器的状态等,实现对CPU的控制。

1. 标志位操作指令

标志位操作指令有7条,可以直接设置或清除CF、DF、IF、标志位,这些指令仅对有关的状态标志位执行操作,而对其他状态标志位则没有影响。

clc      ; CF=0
stc     ; CF=1
cmc     ; CF求反
cld     ; DF=0
std     ; DF=1
cli     ; IF=0,使CPU禁止响应外部的可屏蔽的中断请求
sti     ; IF=1,使CPU允许响应外部的可屏蔽的中断请求

2. CPU控制指令

hlt
  • 处理器暂停指令hlt,使CPU进入暂停状态,这时CPU不进行任何操作。该指令不影响标志位。
  • 当CPU发生复位(RESET)或来自外部的中断(NMI或INTR)时,CPU脱离暂停状态。
  • 该hlt指令可用于程序中等待中断,当程序必须等待中断时,可用hlt,而不必用软件死循环。然后中断使CPU脱离暂停状态,返回执行hlt指令的下一条指令。
  • 注意:该指令在PC中将引起所谓的”死机“,一般的应用程序不要使用。
wait
  • 处理器等待指令wait,在8086/8088的测试引入脚为高电平无效时,使CPU进入等待状态,这时CPU并不做任何操作;测试为低电平有效时,CPU脱离等待状态,继续执行wait指令后面的指令。该指令不影响标志位。
  • 浮点指令经由8086/8088CPU处理发往8087,并与8086/8088本身的整数指令在同一个指令序列;而8087执行浮点数指令较慢,所以8086/8088必须与8087保持同步。8086/8088就是利用wait指令和测试引脚实现与8087同步运行的。
esc extoprd, oprd
  • 处理器交权指令esc,把浮点指令交给浮点处理器执行。为了提高系统的浮点运算能力,8086/8088系统中可加入浮点运算协处理器8087。但是8087的浮点指令是和8086/8088的整数指令组合在一起的,8086/8088主存中存储8087的操作码及其所需的操作数。当8086/8088发现是一条浮点指令时,就利用esc指令将浮点指令交给8087执行。该指令不影响标志位。
  • exroprd,外部操作码(浮点指令的操作码),是一个6位立即数。
  • oprd,源操作数,可以是寄存器或存储器单元。当oprd为寄存器时,它的编码也为操作码;如果oprd为存储器操作数,CPU读出这个操作数送给协处理器。
nop
  • 空操作指令nop不执行任何有意义的操作,但占用一字节存储单元,空耗一个指令执行周期。实际上,nop指令就是xchg ax, ax,它们的机器代码一样。该指令不影响标志位。
  • 在需要预留指令空间时用nop填充,代码空间多余时也可以用nop填充,还可以用nop指令实现软件延时。
lock command
  • 封锁总线前缀指令lock,它是一个指令前缀用于放在指令的前面。这个前缀使得当前指令执行时间内,8086/8088处理器的封锁输出引脚有效,即把总线封锁,使别的控制器不能控制总线,直到该指令执行完后,总线封锁解除。
  • 当CPU与其他处理器协同工作时,lock指令可用于避免破坏有用的信息。
CS: or SS: or DS: or ES:
  • 段超越前缀指令,在允许段超越的存储器操作数之前,使用段超越前缀指令,将不采用默认的寄存器,而是采用指定的段寄存器寻址操作数。

输入输出指令

输入输出指令有两条,,输入指令in用于从外设端口接收数据,输出指令out则向端口发送数据。无论是接收到的数据还是准备发送的数据,都必须先在寄存器AL或AX中。端口的寻址方式有两种,一是直接使用8位立即数n寻址256个端口(0~255),二是间接使用DX寄存器指定16位的地址寻址64K个端口(0~65535)。

1. 输入指令

in al, n ; (AL) = (n)
in ax, n    ; (AX) = (n+1),(n)
in al, dx   ; (AL) = seg:[(DX)]
in ax, dx   ; (AX) = seg:[(DX+1)],seg:[(DX)]

2. 输出指令

out n, al    ; (n) = (AL)
out n, ax   ; (n+1),(n) = (AX)
out dx, al  ; seg:[(DX)] = (AL)
out dx, ax  ; seg:[(DX+1)],seg:[(DX)] = (AX)

汇编语言之8086/8088指令系统相关推荐

  1. 微机笔记2——8086/8088指令系统

    8086/8088寻址方式 寄存器寻址 操作数存放在寄存器中 立即寻址 操作数存放在内存代码段 直接寻址 操作数存放在内存 寄存器间接寻址 操作数存放在内存 变址寻址 操作数存放在内存 基址加变址寻址 ...

  2. 微机原理8086/8088——指令系统与寻址方式

    微机原理8086/8088概念系列 微机原理8086/8088--微型计算机组成 微机原理8086/8088--微处理器功能结构 微机原理8086/8088--内部寄存器 微机原理8086/8088- ...

  3. 汇编语言(四)-8086的指令系统

    8086的指令系统 1. 数据传送指令 1.1 通用数据传送 1.2 地址传送指令 1.3 标志寄存器传送 1.4 累加器专用指令 2. 算术指令 2.1 加法运算指令 2.2 减法运算指令 2.3 ...

  4. 8086/8088 存储器分段概念

    这一节主要讲述8086/8088 存储器分段的概念. 目的 从8086 CPU开始采用了分段的方法管理存储器,只有充分理解存储器分段的概念和存储器逻辑地址和物理地址的关系,才能有助于我们掌握8086/ ...

  5. 8086/8088 CPU寄存器组

    作者:黑剑  出处:http://www.cnblogs.com/blacksword/ 8086/8088 CPU寄存器组 今天来回顾一下8086/8088 CPU寄存器组的知识.其实8086汇编还 ...

  6. 8086/8088 寻址方式补充篇

    作者:黑剑  出处:http://www.cnblogs.com/blacksword/ 8086/8088 寻址方式补充篇 上一节讲述了8086/8088 CPU寻址方式,通过了解它的寻址方式会使得 ...

  7. 【沧海拾昧】微机原理:8086/8088中断系统

    #C0305 沧海茫茫千钟粟,且拾吾昧一微尘 --<沧海拾昧集>@CuPhoenix [阅前敬告] 沧海拾昧集仅做个人学习笔记之用,所述内容不专业不严谨不成体系 如有问题定为本集记录有谬, ...

  8. 8086/8088 寻址方式

    作者:黑剑  出处:http://www.cnblogs.com/blacksword/ 8086/8088 寻址方式 这一节讲解8086/8088寻址方式,所谓寻址方式,就是寻找操作数或操作数地址的 ...

  9. 8086/8088 指令执行流水线断流原因

    8086/8088 指令执行流水线断流原因 1. 指令预取队列中有转移类指令 2. 执行指令需要参数 当指令的执行需要参数时(比如:加法),EU得去获得了参数才可以顺利执行指令,因此此时的并行流水线依 ...

最新文章

  1. linux启动weblogic指令,linux下如何启动和关闭weblogic
  2. docker 安装centos7并SSH远程连接
  3. 理解AppDomain
  4. Python中常用的内置函数(不断更新中)
  5. JavaScrip有哪些优点
  6. vue的slot作用域插槽使用案例
  7. mysql错误码1709_MySQL5.6出现ERROR 1709 (HY000): Index column size too large问题的解决方法...
  8. 第十一天 安装Oracle数据库
  9. WIN10安装和使用MySql5.6中遇到的一些问题与解决
  10. 2014年听写VOA50篇
  11. 【翻译】GRAIL-手写识别
  12. .Net Core报“‘GB2312‘ is not a supported encoding name. For information on defining a custom encod”的错误
  13. 4g网络什么时候淘汰_4G升级5G,4G网络不会被淘汰,与5G继续共存
  14. 计算机械加工工时都需要,机械加工工时(工时定额)计算软件
  15. K3C官改固件更新frp客户端
  16. 03_Linux ARM架构-安装elasticsearch 7.16-银河麒麟V10操作系统
  17. 从阿里、华为、海尔的崛起看:财务生产力可以有多强
  18. 【转载】 中国婚礼 项目流程
  19. Point Estimation
  20. 集线器、路由器、交换机区别

热门文章

  1. Python网络爬虫与文本数据分析!
  2. C\C++ 使用 stringstream 将浮点型转换为字符串,去掉末尾无意义的0
  3. C#新手练习:开发一个应用,模拟移动存储设备的读写
  4. 比windows自带快百倍的文件查找工具-Everything
  5. 历届试题_DNA比对
  6. 如何将你的虚拟机改成汉化版的虚拟机
  7. 性能与便携可兼得:旗舰高能轻薄本雷神T-BOOK系列新品上市
  8. 三星GALAXY Note评测
  9. 开发者模式之—-策略者模式
  10. springboot医院挂号系统的设计与实现毕业设计源码211633