x86汇编知识点汇总

一、进制转换

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  ;$即当前位置计数器

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 .......

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

十五、分支程序设计

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     

(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     

 十六、循环程序设计

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

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

时间: 2024-10-11 06:25:30

x86汇编知识点汇总的相关文章

C++知识点汇总文档

C++知识点汇总文档 持续更新 朝花夕拾. 不写下来, 仿佛一切都没了见证. 编程来源于生活, 无非是对现实的抽象. 整理这份文档的时候我才发现, 自己对C++的了解无非是冰山一角 另, C++11真的太恐怖了, 新"特性"真的是"恐怖如斯" 另注: 本人才疏学浅, 难免有错漏之处, 还望不吝赐教 1.基本概念 内存管理 C++中的内存划分(内容来自博客): 堆 由用户使用new delete关键字管理的内存区域 栈 栈中用来存放临时变量, 比如函数中的局部变量,

赵雅智:js知识点汇总

赵雅智:js知识点汇总,布布扣,bubuko.com

CodeIgniter框架——知识点汇总

NO1.学习要点: 一.CodeIgniter 框架的简介 二.CodeIgniter 框架的安装 三.CodeIgniter 框架的目录结构分析 四.CodeIgniter 框架是如何工作的? 五.CodeIgniter 框架中的控制器.视图.模型及数据库操作 六.CodeIgniter 框架中辅助函数.类库.适配器的学习 七.…… NO2. 一.CodeIgniter 是什么? 1.CodeIgniter 是一个应用程序框架 CodeIgniter 是一个为用 PHP 编写网络应用程序的人员

对X86汇编的理解与入门

本文描述基本的32位X86汇编语言的一个子集,其中涉及汇编语言的最核心部分,包括寄存器结构,数据表示,基本的操作指令(包括数据传送指令.逻辑计算指令.算数运算指令),以及函数的调用规则.个人认为:在理解了本文后,基本可以无障碍地阅读绝大部分标准X86汇编程序.当然,更复杂的指令请参阅Intel相关文档. 1 寄存器. 主要寄存器如下图所示: X86处理器中有8个32位的通用寄存器.由于历史的原因,EAX通常用于计算,ECX通常用于循环变量计数.ESP和EBP有专门用途,ESP指示栈指针(用于指示

《正则表达式》知识点汇总摘录

开园一个月了,但一直没有抽出多少时间,就算有时间,也不知道怎么组织语言记(不是写,是记,写是一个创造的过程,像我这等程序猿,猿嘴吐不出象牙!)点东西!翻翻过去手头整理的一些知识点杂记,然后再结合网上的一些,今天对正则表达式在做一个个人的知识汇总摘录吧!程序员都是共产主义者,一点不假!大部分时候我们只是互联网的搬运工,堆砌者(扯远了,当然成为互联网创造者一直使我们的目标!). 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串&quo

内核基础---AT&T汇编与x86汇编的区别

1.深入Linux内核的前提 因为以前学习过intel的x86汇编语言,所以本文就不在讲述汇编的基本语法了: 内核绝大部分的代码都是用C和汇编语言实现的,要理解内核,C语言大部分的人都已经掌握了,接下来就得首先掌握汇编知识,以便深入理解Linux内核知识!!! 2.学习Linux内核的线路 首先内核有基础部分和深入的部分,我认为应该从一个全局的角度去解读Linux内核,以便我们达到一个更加深刻的认识,从内核的整体架构--->内核源码的解读,并且在这个的过程中不断的去修改代码,编程调试是至关重要的

X86汇编快速入门

本文描述基本的32位X86汇编语言的一个子集,其中涉及汇编语言的最核心部分,包括寄存器结构,数据表示,基本的操作指令(包括数据传送指令.逻辑计算指令.算数运算指令),以及函数的调用规则.个人认为:在理解了本文后,基本可以无障碍地阅读绝大部分标准X86汇编程序.当然,更复杂的指令请参阅Intel相关文档. 1 寄存器. 主要寄存器如下图所示: X86处理器中有8个32位的通用寄存器.由于历史的原因,EAX通常用于计算,ECX通常用于循环变量计数.ESP和EBP有专门用途,ESP指示栈指针(用于指示

C# inline-asm / 嵌入x86汇编

C#可不可以嵌入汇编 可以 在我眼中C#作为一个介于中上层语言是不可能不可以 置入汇编代码的 为什么会被我认为中上层语言呢 从C#保留指针就可以看出 我知 道有很多人一定不会相信C#可以使用汇编代码 不过C#会比较麻烦C#不可以直接 内联汇编(inline-asm)准确的说C#只可以使用(auto-asm)动态汇编 这种技术不是 C#独有的 易语言.VB.C++ 三种语言都可以 不过动态汇编我见过最多的是被应 用在外挂方面 及远程汇编注入 实际上是属于动态汇编技术的一种扩展 不过很难 说JIT在

软考网络工程师易混淆的知识点汇总

网络工程师考试是全国计算机技术与软件水平考试的一项中级资格考试,通过考试的合格人员能根据应用部门的要求进行网络系统的规划.设计和网络设备的软硬件安装调试工作,能进行网络系统的运行.维护和管理,能高效.可靠.安全地管理网络资源,作为网络专业人员对系统开发进行技术支持和指导,具有工程师的实际工作能力和业务水平,能指导网络管理员从事网络系统的构建和管理工作.网络工程师考试是软考的一大热门,怎样才能顺利通过考试是广大考生都想知道的,下面希赛软考学院为您带来网络工程师备考锦囊之应战篇,专业老师整理的网络工