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)手动法:

 1 STACK1    SEGMENT
 2                 DW 20H DUP(?)
 3 TOP           LABEL WORD
 4 STACK1    ENDS
 5 
 6 CODE    SEGMENT
 7 ......
 8 MOV    AX,STACK1
 9 MOV    SS,AX
10 MOV    SP,OFFSET TOP
11 .......
View Code

3.CS的装入:

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

4.DOS返回:

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

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

 1 CODE    SEGMENT
 2 PROC1    PROC    FAR
 3     ASSUME CS:CODE,...
 4 START:    PUSH    DS ;保存PSP首地址,RET返回时将其装入CS
 5                MOV    AX,0
 6                 PUSH    AX  ;RET返回时把00H作为偏移量装入IP
 7                 ...
 8                RET
 9 PROC1    ENDP
10 CODE    ENDS
11             END START
View Code

十五、分支程序设计

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)跳转表由入口地址构成:

 1 DATA    SEGMENT
 2   ATABLE  DW V1,V2
 3       DW V3,V4
 4   N      DB 3
 5   Y      DW 0F786H
 6 DATA    ENDS
 7 STACK1    SEGMENT    STACK
 8   DW    20H DUP(?)
 9 STACK1    ENDS
10 CODE    SEGMENT
11   ASSUME  CS:CODE,DS:DATA,SS:STACK1
12 START:    MOV    AX,DATA
13     MOV    DS,AX
14     MOV    BX,OFFSET ATABLE
15     XOR    AH,AH
16     MOV    AL,N
17     DEC    AL
18     SHL    AL,1
19     ADD    BX,AX
20     JMP    WORD PTR [BX]
21 V1:
22     ADD    Y,100
23     JMP    DONE
24 V2:
25     ADD    Y,99
26     JMP    DONE
27 V3:
28     ADD    Y,98
29     JMP    DONE
30 V4:
31     ADD    Y,97
32     JMP    DONE
33 DONE:    MOV    AH,4CH
34     INT    21H
35 CODE    ENDS
36     END    START
37     
View Code

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

 1 DATA    SEGMENT
 2   N      DB 3
 3   Y      DW 0F786H
 4 DATA    ENDS
 5 STACK1    SEGMENT    STACK
 6   DW    20H DUP(?)
 7 STACK1    ENDS
 8 CODE    SEGMENT
 9   ASSUME  CS:CODE,DS:DATA,SS:STACK1
10 START:    MOV    AX,DATA
11     MOV    DS,AX
12     MOV    CX,OFFSET ATABLE
13     XOR    BH,BH
14     MOV    BL,N
15     DEC    BL
16     MOV    AL,BL
17     SHL    BL,1
18     ADD    BX,CX
19     JMP    BX
20 ATABLE:
21     JMP    V1
22     JMP    V2
23     JMP    V3
24     JMP    V4
25 V1:
26     ADD    Y,100
27     JMP    DONE
28 V2:
29     ADD    Y,99
30     JMP    DONE
31 V3:
32     ADD    Y,98
33     JMP    DONE
34 V4:
35     ADD    Y,97
36     JMP    DONE
37 DONE:    MOV    AH,4CH
38     INT    21H
39 CODE    ENDS
40     END    START
41     
View Code

 十六、循环程序设计

循环控制指令:使用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。

原文地址:https://www.cnblogs.com/jiu0821/p/4180100.html