x86汇编知识点汇总

时间:2023-03-10 04:05:50
x86汇编知识点汇总

目录:

1.进制转换

2.原码、反码、补码

3.寄存器

4.存储器的段结构

5.堆栈

6.传送类指令

7.算术运算类指令(不含乘除)

8.位操作类指令

9.标志位操作指令

10.标识符、常量与变量

11.标号

12.运算符

13.伪指令

14.源程序中段寄存器的装入以及DOS返回

15.分支程序设计

16.循环程序设计

17.子程序设计

18.乘除法运算

19.BCD码校正

20.符号扩展指令

21.串操作指令

内容:

一、进制转换

1.二进制转为十进制:

方法:按权相加法,即将二进制每位上的数乘以权,然后相加之和即是十进制数。

例:(101.101)2=(5.625)10

2.十进制转为二进制:

1)整数部分:

方法:除2取余法(短除法),即每次将整数部分除以2,记录余数,而商继续除以2,继续记录余数,这个步骤一直持续下去,直到商为0为止,最后读数时候,逆序读每一个余数。下面举例: 
例:将十进制的168转换为二进制

得出结果 将十进制的168转换为二进制,(10101000)2 
分析:第一步,将168除以2,商84,余数为0。 
第二步,将商84除以2,商42余数为0。 
第三步,将商42除以2,商21余数为0。 
第四步,将商21除以2,商10余数为1。 
第五步,将商10除以2,商5余数为0。 
第六步,将商5除以2,商2余数为1。 
第七步,将商2除以2,商1余数为0。 
第八步,将商1除以2,商0余数为1。 
第九步,读数,因为最后一位是经过多次除以2才得到的,因此它是最高位,读数字从最后的余数向前读,即10101000

2) 小数部分 
方法:乘2取整法,即将小数部分乘以2,然后取整数部分,剩下的小数部分继续乘以2,然后取整数部分,剩下的小数部分又乘以2,一直取到小数部分 
为零为止。如果永远不能为零,就同十进制数的四舍五入一样,按照要求保留多少位小数时,就根据后面一位是0还是1,取舍,如果是零,舍掉,如果是1,向入一位。换句话说就是0舍1入。读数要从前面的整数读到后面的整数,下面举例: 
例1:将0.125换算为二进制

得出结果:将0.125换算为二进制(0.001)2 
分析:第一步,将0.125乘以2,得0.25,则整数部分为0,小数部分为0.25; 
第二步, 将小数部分0.25乘以2,得0.5,则整数部分为0,小数部分为0.5; 
第三步, 将小数部分0.5乘以2,得1.0,则整数部分为1,小数部分为0.0; 
第四步,读数,从第一位读起,读到最后一位,即为0.001。

3.在二进制与八进制、十六进制转化的时候,三位二进制位对应一位八进制位,四位二进制位对应一位十六进制位。

4.其他进制间的转化可以借助十进制与二进制的转化。

二、原码、反码、补码

1.原码即真值+符号位。反码即原码取反。补码即反码+1。

2.由负数的真值或原码变补码的方法:自最低位向高位逐位检查,遇到第一个‘1’及以前(较低位)的各位‘0’保持不变,以后各高位取反。若是原码变补码,因最高位为符号位,不改变。

3.内存里皆以补码表示。对一个数求补,即求负。

4.反码算数运算若有进位则要回送给最低位,而补码算数运算若有进位则舍弃。

三、寄存器

1、寄存器汇总

AX(AH、AL)累加器;

BX(BH、BL)基址寄存器;

CX(CH、CL)计数寄存器;

DX(DH、DL)数据寄存器;

SP                 堆栈指针;

BP      基址指针;

SI      源变址寄存器;

DI      目的变址寄存器;

IP       指令指针;

FLAGS    标志寄存器;

CS      代码段寄存器;

DS      数据段寄存器;

SS      堆栈段寄存器;

ES      附加段寄存器。

其中,通用寄存器有:AX,BX,CX,DX,SP,BP,SI,DI。

2、标志寄存器的各标志位(复位(0)、置位(1))

1)溢出位OF,置位OV,复位NV。判断运算结果是否超出补码范围。溢出则置位。

2)方向位DF,置位DN,复位UP。决定串操作指令执行时指针寄存器的调整方向。DF=0时,正向处理(低位->高位),SI/DI递增。反之,亦然。

3)中断位IF,置位EI,复位DI。

4)符号位SF,置位NG,复位PL。与运算结果的最高位相一致。

5)零值位ZF,置位ZR,复位NZ。若运算结果为0,置位。否则,清0。

6)辅助进位位AF,置位AC,复位NA。若低4位出现进位或者借位,置位。否则,清0。

7)奇偶位PF,置位PE,复位PO。若运算结果低8位中‘1’个数为偶,则置位。否则,清0。

8)进位位CF,置位CY,复位NC。若最高位进位或者借位,则置位。在移位类指令中用来保存移出的0或1。

四、存储器的段结构

1.逻辑段的开始地址必须是任一小节的首地址。自0地址开始,每16字节为一小节。1MB的存储空间为65536小节。

2.逻辑段最大为1MB,最小为16B。

3.物理地址=16位段基值*16+偏移量

五、堆栈

1.在x86中,堆栈向下增长,是按字组织的,即最小数据单元为一个字。

2.当SP初始化时,它指向栈底+2字节单元,它的值就是这个堆栈的长度。

3.BP作为基址,一直不变;而SP作为栈顶指针,随栈顶的移动而移动。

4.压栈:PUSH。两步:SP<=SP-2;SP<=数据。

出栈:POP。两步:数据单元<=SP;SP<=SP+2。

PUSHF:将标志寄存器内容压栈。

POPF:将栈顶一个字数据送入标志寄存器。

六、传送类指令:源操作数与目的操作数类型必须一致(即同一个字节或字大小)。

1.MOV:MOV DEST,SRC  功能:DEST<=SRC。

源操作数与目的操作数不可同时为存储单元。对FLAGS没有影响。

2.XCHG:XCHG DEST,SRC  功能:交换DEST与SRC内容。

源操作数与目的操作数不可同时为存储单元。对FLAGS没有影响。

3.LAHF:LAHF  功能:将FLAGS低8位传送至AH,即把SF,ZF,AF,PF,CF分别传送至AH的第7,6,4,2,0位,AH其他位任意值。

对FLAGS没有影响。

4.SAHF:SAHF  功能:将AH的内容送入FLAGS低8位。

只影响SF,ZF,AF,PF,CF位。

5.PUSHF:PUSHF  功能:将标志寄存器内容压栈。

对FLAGS没有影响。

6.POPF:POPF  功能:将栈顶一个字数据送入标志寄存器。

影响FLAGS所有的位。

7.LEA:LEA DEST,SRC  功能:将SRC的有效地址EA送入DEST。其中,SRC必须为一个字节或字的存储器操作数,DEST必须为一个16位的通用寄存器。

对FLAGS没有影响。

8.LDS/LES:LDS/LES DEST,SRC  功能:将SRC所指32位存储单元的低16位送入DEST,而高16位送入DS(LDS指令)或ES(LES指令)。其中,DEST必须为一个16位通用寄存器,SRC必须是一个存储器操作数,该地址单元中存放着32位地址,低16位是偏移量,高16位是段基址。

对FLAGS没有影响。

9.XLAT (OPR):XLAT  (OPR)  功能:AL<=[BX+AL],即将BX与AL相加形成EA,再将地址对应的字节存储单元内容送入AL中。OPR可写可不写,没有实际作用,只是为了增加程序可读性而设置的,其内容为一个偏移量,和BX内容相同,存放一个表格的首地址。

对FLAGS没有影响。

七、算术运算类指令(不含乘除):源操作数与目的操作数类型必须一致(即同一个字节或字大小)。

1.ADD:ADD DEST,SRC  功能:DEST<=DEST+SRC

源操作数与目的操作数不可同时为存储单元。该指令会根据运算结果设置FLAGS的CF、PF、AF、ZF、SF和OF位。

2.ADC:ADC DEST,SRC  功能:DEST<=DEST+SRC+CF。带进位的加法。

源操作数与目的操作数不可同时为存储单元。该指令会根据运算结果设置FLAGS的CF、PF、AF、ZF、SF和OF位。

3.INC:INC DEST  功能:DEST<=DEST+1   其中,DEST可以为通用寄存器,也可以为存储单元。

该指令会根据运算结果设置FLAGS的PF、AF、ZF、SF和OF位,但不影响CF位。

4.SUB:SUB DEST,SRC   功能:DEST<=DEST-SRC

源操作数与目的操作数不可同时为存储单元。该指令会根据运算结果设置FLAGS的CF、PF、AF、ZF、SF和OF位。

5.SBB:SBB DEST,SRC  功能:DEST<=DEST-SRC-CF。带借位的减法。

源操作数与目的操作数不可同时为存储单元。该指令会根据运算结果设置FLAGS的CF、PF、AF、ZF、SF和OF位。

6.DEC:DEC DEST  功能:DEST<=DEST-1   其中,DEST可以为通用寄存器,也可以为存储单元。

该指令会根据运算结果设置FLAGS的PF、AF、ZF、SF和OF位,但不影响CF位。

7.NEG:NEG DEST  功能:DEST<=0-DEST  求补运算,也可以说是求负运算。

若字节操作数为-128(80H)或字操作数为-32768(8000H)时,该指令执行后,操作数不变,OF置位;否则,OF复位。若操作数为0,那么结果不变,CF复位;否则,置位。

该指令会根据运算结果设置FLAGS的CF、PF、AF、ZF、SF和OF位。

8.CMP:CMP DEST,SRC  功能:与SUB基本相同,唯一不同的是目的操作数不变。

源操作数与目的操作数不可同时为存储单元。该指令会根据运算结果设置FLAGS的CF、PF、AF、ZF、SF和OF位。

八、位操作类指令:源操作数与目的操作数类型必须一致(即同一个字节或字大小)

1.AND:AND DEST,SRC  功能:DEST<=DEST&SRC

源操作数与目的操作数不可同时为存储单元。该指令会根据运算结果设置FLAGS的PF、ZF、SF位,CF和OF位总复位,AF位不确定。

2.TEST:TEST DEST,SRC  功能:与AND基本相同,唯一不同的是,DEST不变。常用于测试目的操作数的某一位或某几位的状态。

源操作数与目的操作数不可同时为存储单元。该指令会根据运算结果设置FLAGS的PF、ZF、SF位,CF和OF位总复位,AF位不确定。

3.OR:OR DEST,SRC  功能:DEST<=DEST|SRC

源操作数与目的操作数不可同时为存储单元。该指令会根据运算结果设置FLAGS的PF、ZF、SF位,CF和OF位总复位,AF位不确定。

4.XOR:XOR DEST,SRC  功能:DEST<=DEST^SRC

源操作数与目的操作数不可同时为存储单元。该指令会根据运算结果设置FLAGS的PF、ZF、SF位,CF和OF位总复位,AF位不确定。

5.NOT:NOT DEST  功能:DEST<=~DEST(按位取反)

对FLAGS无影响。

6.SAL:SAL DEST,COUNT  功能:DEST<=DEST<<COUNT   算数左移指令:左移COUNT位,每移动一位,最低位补0,移出的最高位送入CF位。其中,如果COUNT=1,指令中可直接用1代替COUNT的位置;如果COUNT>1,那么必须用CL来代替COUNT的位置,移位位数由CL决定。

该指令会根据运算结果设置FLAGS的CF、PF、ZF、SF和OF位,AF位不确定。若移位位数为1次,且移位前后DEST最高位发生变化,则OF置位,否则复位。若移位位数>1,那么OF不确定。

7.SAR:SAR DEST,COUNT  功能:DEST<=DEST>>COUNT   算数右移指令:右移COUNT位,每移动一位,最高位补原有值,移出的最低位送入CF位。其中,如果COUNT=1,指令中可直接用1代替COUNT的位置;如果COUNT>1,那么必须用CL来代替COUNT的位置,移位位数由CL决定。

该指令会根据运算结果设置FLAGS的CF、PF、ZF、SF和OF位,AF位不确定。若移位位数为1次,且移位前后DEST最高位发生变化,则OF置位,否则复位。若移位位数>1,那么OF不确定。

8.SHL:SHL DEST,COUNT   功能:与SAL完全相同     逻辑左移指令

9.SHR:SHR DEST,COUNT  功能:逻辑右移指令:将DEST右移COUNT位,每移动一位,最高位补0,移出的最低位送入CF位。其中,如果COUNT=1,指令中可直接用1代替COUNT的位置;如果COUNT>1,那么必须用CL来代替COUNT的位置,移位位数由CL决定。

该指令会根据运算结果设置FLAGS的CF、PF、ZF、SF和OF位,AF位不确定。若移位位数为1次,且移位前后DEST最高位发生变化,则OF置位,否则复位。若移位位数>1,那么OF不确定。

10.ROL:ROL DEST,COUNT   功能:循环左移指令:每移动一位,把移出的最高位送入最低位和CF位。其中,如果COUNT=1,指令中可直接用1代替COUNT的位置;如果COUNT>1,那么必须用CL来代替COUNT的位置,移位位数由CL决定。

只影响FLAGS的CF和OF位。若移位位数为1次,且移位前后DEST最高位发生变化,则OF置位,否则复位。若移位位数>1,那么OF不确定。

11.ROR:ROR DEST,COUNT   功能:循环右移指令:每移动一位,把移出的最低位送入最高位和CF位。其中,如果COUNT=1,指令中可直接用1代替COUNT的位置;如果COUNT>1,那么必须用CL来代替COUNT的位置,移位位数由CL决定。

只影响FLAGS的CF和OF位。若移位位数为1次,且移位前后DEST最高位发生变化,则OF置位,否则复位。若移位位数>1,那么OF不确定。

12.RCL:RCL DEST,COUNT   功能:带进位的循环左移指令:每移动一位,把CF位送入最低位,把移出的最高位送入CF位。其中,如果COUNT=1,指令中可直接用1代替COUNT的位置;如果COUNT>1,那么必须用CL来代替COUNT的位置,移位位数由CL决定。

只影响FLAGS的CF和OF位。若移位位数为1次,且移位前后DEST最高位发生变化,则OF置位,否则复位。若移位位数>1,那么OF不确定。

13.RCR:RCR DEST,COUNT   功能:带进位的循环右移指令:每移动一位,把CF位送入最高位,把移出的最低位送入CF位。其中,如果COUNT=1,指令中可直接用1代替COUNT的位置;如果COUNT>1,那么必须用CL来代替COUNT的位置,移位位数由CL决定。

只影响FLAGS的CF和OF位。若移位位数为1次,且移位前后DEST最高位发生变化,则OF置位,否则复位。若移位位数>1,那么OF不确定。

九、标志位操作指令:

1.CLC:CLC   功能:CF=0

2.STC:STC   功能:CF=1

3.CMC:CMC   功能:CF=~CF

4.CLD:CLD   功能:DF=0

5.STD:STD   功能:DF=1

6.CLI:CLI   功能:IF=0

7.STI:STI   功能:IF=1

十、标识符、常量与变量

1.标识符组成规则:(无大小写区分)

(1)最多由31个字符组成;

(2)必须是以字母、‘?’、‘@’或‘_'开始;

(3)除第一个字符外,可以是字母、数字、‘?’、‘@’或‘_';

(4)不能是系统专用保留字。

2.常量表示:

(1)二进制常量:B(b)后缀;

(2)十进制常量:D(d)后缀,可省略;

(3)八进制常量:Q(q)或O(o)后缀;

(4)十六进制常量:H(h)后缀。对于A~F或a~f开头的十六进制数,必须在其前加一个0,以便与标识符区分开。

(5)实数常量:通常以十进制表示,由整数、小数和指数三部分组成。eg:-1.23E-4;9.0E+4。实数必须由伪指令DD、DQ、DT定义,实数不能出现在表达式中。另外,实数也可以用十六进制数直接说明其二进制数编码形式,但是这个十六进制数必须以0~9开头,不带符号,并在用R作后缀。

(6)字符串常量:用单引号括起来的一个或多个字符。有大小写区分。

3.变量定义:DB(字节变量)、DW(字变量)、DD(双字变量)、DQ(四字变量)、DT(五字变量)。

4.变量属性:

(1)SEG:所在段的段基值;

(2)OFFSET:距离段基址的字节数(偏移量);

(3)TYPE:所占存储单元的字节数。

5.变量预置:

(1)数值表达式:eg:VA  DW  1234H,0ABCDH   (依次以小尾方式存储,前一个单元12H放高字节,34H放低字节,后一单元同样)

(2)字符串表达式:每一个字符占一个字节单元。

1)使用DB:字符串不超过255个字符,大尾方式存放。eg:VA  DB  'ABCDEF'    (从’A'至'F'按地址递增排列)

2)使用DW:最多为两个字符组成的字符串分配存储单元,小尾方式存放。eg:VA  DW  'AB','CD','EF'    (地址递增排序为:'BADCFE')

3)使用DD:最多为两个字符组成的字符串分配存储单元,小尾方式存放,且第2个字单元存放0000H。eg:VA  DD  'AB','CD'  (地址递增排序为:'B''A''00''00''D''C''00''00')

(3)?表达式:预置随机值。eg:VA  DB  ?,?

(4)地址表达式:若该地址表达式为一变量名或者标号名,那么DW定义则是用其偏移量预置;DD定义则是用其段基值和偏移量预置,且段基值存高字单元,偏移量存低字单元。eg:VB  DD  VA    (VB的高字单元存放VA的段基值,低字单元存VA的偏移量)

(5)带DUP的表达式:格式:变量名 伪指令 n DUP(表达式)       功能:定义重复数据。

eg:VA      DW  10H DUP(4)     (即分配了10H个字单元,都每个字单元预置4)      VB  DB  10H DUP('ABCD')     (分配了10H个字符串’ABCD‘,共10H*4=40H个字节)

DUP可以嵌套使用。

eg:VA  DB  10H DUP(4 DUP(2),3,4)等价于 VA  DB  10H DUP(2,2,2,2,3,4)

(6)混合使用:eg:VA  DB  2 DUP(1),2 DUP(2,'B'),'123',1,2

十一、标号

1.属性:

(1)SEG:所在段的段基值;

(2)OFFSET:距离段基址的字节数(偏移量);

(3)类型属性Distance:NEAR、FAR。

2.类型属性设置:

(1)缺省默认NEAR。

(2)LABEL伪指令方式:建立新的标号并赋予指定类型属性。

eg:J1  LABEL  FAR

  J2:  MOV  AX,20H

两个标号J1和J2指向同一个地方,但类型属性不同。

十二、运算符

1.算术运算符:+、-、*、/、MOD、[]。

2.移位运算符:SHR(右移),SHL(左移)       eg:MOV  AX,11011011B SHL 3等价于MOV  AX,1101011000B

3.逻辑运算符:NOT、AND、OR、XOR     eg:MOV  AX,NOT  0F0H

4.关系运算符:EQ(相等为真A=B)、NE(不相等为真A!=B)、LT(A<B)、LE(A<=B)、GT(A>B)、GE(A>=B)。表达式都是常数或者同段的偏移量。如果是常数,按照无符号数比较;如果是变量,比较其偏移量。比较结果以真(全1)或假(全0)给出。   eg:MOV  AX,0FH EQ  1111B等价于MOV  AX,0FFFFH

5.数值返回运算符:

(1)SEG:返回变量或者标号的段基值。  eg:MOV  AX,SEG VA

(2)OFFSET:返回变量或标号的偏移量。eg:MOV  AX,OFFSET  VA

(3)TYPE:返回变量或标号的类型属性的数字形式:变量(BYTE(1)、WORD(2)、DWORD(4))、标号(NEAR(-1)、FAR(-2))      eg:MOV  AX,TYPE  VA

(4)LENGTH:仅用于变量之前,返回数组变量的元素个数。如果变量包含DUP,那么返回其重复值n;否则,返回1。  eg:MOV  AX,LENGTH VA

(5)SIZE:仅用于变量之前,返回数组变量所占的总字节数,即等价于LENGTH与TYPE的乘积。  eg:MOV  AX,SIZE VA

6.属性修改运算符:

(1)PTR:格式:类型 PTR 地址表达式       其中,地址表达式是指要修改或指定类型属性的标号、变量或用做地址指针的寄存器。不过,此修改仅在PTR语句里生效,临时修改而已。              eg:MOV  AX,WORD PTR DATA_BYTE[10]                    MOV  WORD PTR [SI],30H

(2)HIGH和LOW:只放在一个常数或在能确定其段基值或偏移量的地址表达式前面,用来分离运算对象的高字节和低字节。

eg:CONST  EQU  0ABCDH

  MOV  AH,HIGH  CONST

eg2:MOV  BH,HIGH(SEG  DA1)

十三、伪指令

1.EQU:等值伪指令:格式:符号名 EQU 表达式       其中,表达式可以是常数、数值表达式、字符串、地址表达式、标号、变量、指令助记符或关键字等。

eg:CONT EQU 5  ADR EQU ES:10H[BX]  VA EQU AX  VA EQU ADD。

不能重复定义,除非解除原先定义。

PURGE:用来解除EQU的定义。eg:PURGE CONT,ADR  注意:不能用PURGE解除被PUBLIC说明的符号的定义

2.=:格式:符号名=表达式。eg:CONT=5

与EQU的区别:(1)=允许重复定义;(2)=后的表达式不能是指令助记符或关键字。

3.DB(字节变量)、DW(字变量)、DD(双字变量)、DQ(四字变量)、DT(五字变量)

4.LABEL:与PTR功能相同,并且作用不受限制。

(1)改变标号属性:见前面的(十一.2.(2))。

(2)改变变量属性:

eg:VA  LABEL  BYTE

  VB  DW    20H DUP(0)

VA与VB段基值、偏移量都相同,但类型不相同。

5.段定义伪指令

格式:段名 SEGMENT [定位类型][组合类型][类别名]

     ......

   段名 ENDS

6.ASSUME:段寻址伪指令,指定逻辑段与段寄存器之间的关系。eg:ASSUME CS:CODE,DS:DATA

注意:(1)该指令不产生机器码。

   (2)若不指定,程序中使用变量名或地址表达式时要加上段前缀。eg:MOV  AX,ES:VA

   (3)该指令也可以取消或修改指定关系。

eg:ASSUME  ES:NOTHING  ;删除对ES的关联                ASSUME NOTHING  ;删除所有关联

7.PROC/ENDP:过程定义伪指令。

格式:过程名 PROC [NEAR/FAR]

   ......

   RET

   ......

   过程名 ENDP

8.ORG/$:定位伪指令和当前位置计数器。

eg:ORG  30H;该语句之后的指令或数据以当前值30H作为起始偏移量。       eg:ORG  $+20H  ;$即当前位置计数器

注意:ORG后的表达式以65536为模进行计算,即两个字节;而$与变量做减法时值为一个字节,如:VA2 EQU $-VA    此时VA2占据一个字节的内存。

9.TITLE:标题伪指令。格式:TITLE 标题名

10.END:程序结束伪指令。格式:END 起始地址              功能:一方面表示什么时候结束程序,一方面指定程序装入内存时根据起始地址对CS和IP装入对应的段基值和偏移量。

11.PUBLIC/EXTRN:前者用来定义全局符号,后者用来标明当前模块中要访问的本模块之外的符号。

十四、源程序中段寄存器的装入以及DOS返回

1.DS和ES的装入:

DS:MOV AX,DATA         MOV DS,AX

ES:MOV AX,DATA2         MOV ES,AX

2.SS的装入:

(1)系统自动装入:在定义堆栈逻辑段时,指定其组合类型为STACK,并在ASSUME中关联。eg:STACK1 SEGMENT STACK    ........

(2)手动法:

 STACK1    SEGMENT
DW 20H DUP(?)
TOP LABEL WORD
STACK1 ENDS CODE SEGMENT
......
MOV AX,STACK1
MOV SS,AX
MOV SP,OFFSET TOP
.......

3.CS的装入:

一般方法:程序结束伪指令END直接搞定,装入CS和IP。格式:END 起始地址

4.DOS返回:

(1)用4CH系统功能调用实现返回:即在程序结束时加上:MOV  AH,4CH                 INT  21H

(2)用程序段前缀实现返回:三步:1)把程序编制成一个过程,设置为FAR。2)把PSP起始地址压栈。3)程序结束时RET。

 CODE    SEGMENT
PROC1 PROC FAR
ASSUME CS:CODE,...
START: PUSH DS ;保存PSP首地址,RET返回时将其装入CS
MOV AX,
PUSH AX ;RET返回时把00H作为偏移量装入IP
...
RET
PROC1 ENDP
CODE ENDS
END START

十五、分支程序设计

1.无条件转移指令JMP:不影响FLAGS。

(1)段内转移:只需要修改IP值。

1)直接寻址:JMP TARGET  (TARGET为标号)    指令编码2~3字节。

2)间接寻址:JMP REG或者JMP ADDR   (REG为寄存器,ADDR为字存储单元,存储着目标地址)  指令编程2~4字节

eg:JMP CX;             JMP WORD PTR [BX];              JMP VA;

(2)段间转移:需要修改CS和IP值。

1)直接寻址:JMP TARGET  指令编码5字节。

2)间接寻址:JMP ADDR  (ADDR为双字存储单元,存储目标地址)      指令编码2~4字节             eg:JMP DWORD PTR VA[BX]

2.条件转移指令:格式:JXX TARGET    (TARGET为标号)      执行的操作:IP<=TARGET的偏移量                  指令编码都是2字节。

该系列指令只能在段内直接寻址,并且转移范围在从下一条指令算起的-128~127个字节的地址范围内。且不影响FLAGS。

(1)简单条件转移指令:

JC     CF=1  有进位/借位

JNC     CF=0  无进位/借位

JE/JZ     ZF=1  相等/等于0

JNE/JNZ   ZF=0  不相等/不等于0

JS      SF=1  为负数

JNS    SF=0  为正数

JO      OF=1  有溢出

JNO    OF=0  无溢出

JP/JPE     PF=1  有偶数个1

JNP/JPO   PF=0  有奇数个1

(2)无符号数条件转移指令:假设此指令前进行无符号数A、B的比较,指令的操作为A-B

JA/JNBE  CF=0&&ZF=0  A>B

JAE/JNB  CF=0||ZF=1   A>=B

JB/JNAE  CF=1&&ZF=0  A<B

JBE/JNA  CF=1||ZF=1    A<=B

(3)有符号数条件转移指令:假设此指令前进行有符号数A、B的比较,指令的操作为A-B

JG/JNLE  SF=OF&&ZF=0  A>B

JGE/JNL  SF=OF||ZF=1   A>=B

JL/JNGE  SF!=OF&&ZF=0  A<B

JLE/JNG  SF!=OF||ZF=1  A<=B

3.对于多路分支,可以使用跳转表法。

(1)跳转表由入口地址构成:

 DATA    SEGMENT
ATABLE DW V1,V2
DW V3,V4
N DB
Y DW 0F786H
DATA ENDS
STACK1 SEGMENT STACK
DW 20H DUP(?)
STACK1 ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK1
START: MOV AX,DATA
MOV DS,AX
MOV BX,OFFSET ATABLE
XOR AH,AH
MOV AL,N
DEC AL
SHL AL,
ADD BX,AX
JMP WORD PTR [BX]
V1:
ADD Y,
JMP DONE
V2:
ADD Y,
JMP DONE
V3:
ADD Y,
JMP DONE
V4:
ADD Y,
JMP DONE
DONE: MOV AH,4CH
INT 21H
CODE ENDS
END START

(2)跳转表由JMP指令构成:

 DATA    SEGMENT
N DB
Y DW 0F786H
DATA ENDS
STACK1 SEGMENT STACK
DW 20H DUP(?)
STACK1 ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK1
START: MOV AX,DATA
MOV DS,AX
MOV CX,OFFSET ATABLE
XOR BH,BH
MOV BL,N
DEC BL
MOV AL,BL
SHL BL,
ADD BX,CX
JMP BX
ATABLE:
JMP V1
JMP V2
JMP V3
JMP V4
V1:
ADD Y,
JMP DONE
V2:
ADD Y,
JMP DONE
V3:
ADD Y,
JMP DONE
V4:
ADD Y,
JMP DONE
DONE: MOV AH,4CH
INT 21H
CODE ENDS
END START

 十六、循环程序设计

循环控制指令:使用CX作为计数器,采用段内直接寻址,操作数为标号,不影响FLAGS。格式都是:LOOP TARGET。指令编码2字节。并且转移范围在从下一条指令算起的-128~127个字节的地址范围内。

LOOP:     首先CX<=CX-1。如果CX!=0,则IP<=TARGET的偏移量;否则,顺序执行。

LOOPZ/LOOPE:首先CX<=CX-1。如果CX!=0&&ZF=1,则IP<=TARGET的偏移量;否则,顺序执行。

LOOPNZ/LOOPNE:首先CX<=CX-1。如果CX!=0&&ZF!=1,则IP<=TARGET的偏移量;否则,顺序执行。

JCXZ:      测试CX==0,但不修改其值。如果CX=0,则IP<=TARGET的偏移量;否则,顺序执行。

十七、子程序设计

1.子程序定义格式:

过程名 PROC [NEAR/FAR]

   ......

   RET

   ......

过程名 ENDP

2.段内调用:

(1)直接调用:CALL PROC_NAME(过程名)      指令操作:将IP压栈,IP<=子程序入口偏移量                指令编码3字节

(2)间接调用:CALL REG或者CALL W_ADDR  (操作数为通用寄存器或者变量、标号)            指令操作:将IP压栈,IP<=REG/W_ADDR.     指令编码2~4字节

3.段间调用:

(1)直接调用:CALL PROC_NAME(FAR属性)           指令操作:依次将CS、IP压栈,CS<=子程序段基值,IP<=子程序偏移量。         指令编码5字节。

(2)间接调用:CALL DW_ADDR        (操作数为变量或标号)             指令操作:依次将CS、IP压栈,IP<=第一个字存储单元内容,CS<=第二个字存储单元内容。         指令编码2~4字节。

4.返回指令RET:

(1)段内返回:RET 或 RET n(n为偶数)。     指令操作:对IP出栈。如果带有n,则SP<=SP+n。           不带操作数时编码为C3,单字节;带操作数时3字节。

(2)段间返回:RET 或 RET n(n为偶数)。     指令操作:先对IP出栈,再对CS出栈。如果带有n,则SP<=SP+n。  不带操作数时编码为CB,单字节;带操作数时3字节。

其中,RET n的作用是将call指令前压栈的参数数据占据的空间释放。

5.子程序与主程序之间的参数传递可以通过寄存器、堆栈或者地址表实现。这里不表。

十八、乘除法运算

1.无符号数乘法MUL:MUL OPRD     只影响FLAGS中的CF和OF。若乘积的高半部分不为0,则CF=OF=1;否则,CF=OF=0。其他标志位不确定。

字节乘法:AX=AL*OPRD     乘积放入AX中。

字乘法:   DX:AX=AX*OPRD      乘积的高字放入DX,低字放入AX。

2.带符号数乘法IMUL:IMUL OPRD         只影响FLAGS中的CF和OF。如果乘积的高半部分不是低半部分的符号扩展,则CF=OF=1;否则,CF=OF=0。其他标志位不确定。

字节乘法:AX=AL*OPRD     乘积放入AX中。

字乘法:   DX:AX=AX*OPRD      乘积的高字放入DX,低字放入AX。

3.无符号数除法DIV:DIV OPRD     不影响FLAGS。

字节除法:被除数AX  除数OPRD  商AL  余数AH

字除法:   被除数DX:AX除数OPRD  商AX  余数DX

如果除数为0或者商AL>0FFH或者AL>0FFFFH,转入0型中断。

4.带符号数除法IDIV:IDIV OPRD    不影响FLAGS。

字节除法:被除数AX  除数OPRD  商AL  余数AH

字除法:   被除数DX:AX除数OPRD  商AX  余数DX

如果除数为0或者商AL>7FH或者AL>7FFFH,转入0型中断。

十九、BCD码校正:需要注意的是,除法校正指令写在除法运算指令之前,而其他指令都是写在相应运算指令之后。

1.x86采用先用二进制运算指令进行算术运算,再用BCD码校正。

2.组合型BCD码:一个字节表示两个十进制数;

非组合型BCD码:一个字节只表示一位十进制数。

3.非组合型加法校正指令AAA:若AL中低4位的数>9,或AF=1,则AL<=AL+6,AH<=AH+1,且AL中高4位清0,AF、CF置一。

4.组合型加法校正指令DAA:若AL中低4位>9或者AF=1,则AL<=AL+6,并置AF=1。

              若AL中高4位>9或者CF=1,则AL<=AL+60H,并置CF=1。

5.非组合型减法校正指令AAS:若AL中低4位>9或者AF=1,则依次执行:AL<=AL-6,AH<=AH-1,AL高4位清0,CF=AF=1。

6.组合型减法校正指令DAS:若AL中低4位>9或者AF=1,则AL<=AL-6,并置AF=1。

              若AL中高4位>9或者CF=1,则AL<=AL-60H,并置CF=1。

7.非组合型乘法校正指令AAM:对在AL中的积(由两个组合的BCD码相乘的结果)进行校正,产生两个非组合的BCD码。

               指令的操作:把AL的值除以10,商放在AH中,余数放在AL中。

该指令影响FLAGS的SF、ZF和PF。

8.非组合型除法校正指令AAD:把存放在AH和AL中的两位非组合BCD码调整为一个二进制数,存放在AL中。

               指令的操作:AL<=AH*10+AL,AH=0。

该指令影响FLAGS的SF、ZF和PF。

二十、符号扩展指令

1.字节扩展为字 CBW:CBW   功能:当AL最高位为1,则AH变为1111B;当AL最高位为0,则AH变为0000B。

不影响FLAGS。

2.字扩展为双字 CWD:CWD   功能:当AX最高位为1,则DX变为FFFFH;当AX最高位为0,则DX变为0000H。

不影响FLAGS。

二十一、串操作指令

1.串操作指令的源操作数地址由DS:[SI]提供,目的串操作数地址由ES:[DI]提供。每条串操作指令每次仅对串中的一个字或字节单元进行操作,且同时自动修改SI或者DI。若DF=0,则SI/DI递增1个字节或字;若DF=1,则SI/DI递减1个字节或字。还有重复前缀指令,重复次数由CX决定。

2.1.取串指令LODS:LODS 源串

                 LODSB   ;取源串一个字节         等价于:MOV  AL,[SI]                             INC/DEC  SI

              LODSW  ;取源串一个字            等价于:MOV  AX,[SI]              ADD/SUB  SI,2

不影响FLAGS。

2.2.存串指令STOS:STOS 目的串

                 STOSB   ;送入目的串一个字节         等价于:MOV  [DI],AL                             INC/DEC  DI

             STOSW  ;送入目的串一个字            等价于:MOV    [DI],AX              ADD/SUB  DI,2

不影响FLAGS。

2.3.串传送指令MOVS:MOVS 目的串,源串

                    MOVSB   ;字节传送                     等价于:把BYTE PTR [SI]传给[DI],并修改SI和DI。

             MOVSB   ;字传送                     等价于:把WORD PTR [SI]传给[DI],并修改SI和DI。

不影响FLAGS。

2.4.串比较指令CMPS:CMPS 源串,目的串

             CMPSB     ;字节比较

             CMPSW    ;字比较

影响FLAGS。

需要注意的是:串比较指令在比较时是源操作数减目的操作数,而一般比较指令是目的操作数减源操作数。

2.5.串搜索指令SCAS:SCAS 目的串

       SCASB

         SCASW

影响FLAGS。

查找方法:在目的串中找AX或AL指定的内容。用AX或AL内容减去目的串中一个字或字节,相减结果反映在FLAGS中。每查找一次,按照DF修改DI。

3.重复前缀指令REP:前面的指令都是操作一个字节或字,若操作一个字符串,则可用REP指令。每执行一次串操作指令,CX减1,直到CX=0为止。

REP:重复执行条件是:CX!=0                           用于LODS、STOS、MOVS对应指令之前。

REPE/REPZ:重复执行条件是:CX!=0&&ZF=1。  用于CMPS、SCAS对应指令之前。

REPNE/REPNZ:重复执行条件是:CX!=0&&ZF=0。  用于CMPS、SCAS对应指令之前。

实验部分:可以参考http://wenku.baidu.com/view/8d9f9aef0975f46527d3e10b.html。