首页 > 代码库 > x86汇编知识点汇总
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,AX10 MOV SP,OFFSET TOP11 .......
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 ENDP10 CODE ENDS11 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 ENDS10 CODE SEGMENT11 ASSUME CS:CODE,DS:DATA,SS:STACK112 START: MOV AX,DATA13 MOV DS,AX14 MOV BX,OFFSET ATABLE15 XOR AH,AH16 MOV AL,N17 DEC AL18 SHL AL,119 ADD BX,AX20 JMP WORD PTR [BX]21 V1:22 ADD Y,10023 JMP DONE24 V2:25 ADD Y,9926 JMP DONE27 V3:28 ADD Y,9829 JMP DONE30 V4:31 ADD Y,9732 JMP DONE33 DONE: MOV AH,4CH34 INT 21H35 CODE ENDS36 END START37
(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:STACK110 START: MOV AX,DATA11 MOV DS,AX12 MOV CX,OFFSET ATABLE13 XOR BH,BH14 MOV BL,N15 DEC BL16 MOV AL,BL17 SHL BL,118 ADD BX,CX19 JMP BX20 ATABLE:21 JMP V122 JMP V223 JMP V324 JMP V425 V1:26 ADD Y,10027 JMP DONE28 V2:29 ADD Y,9930 JMP DONE31 V3:32 ADD Y,9833 JMP DONE34 V4:35 ADD Y,9736 JMP DONE37 DONE: MOV AH,4CH38 INT 21H39 CODE ENDS40 END START41
十六、循环程序设计:
循环控制指令:使用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。
x86汇编知识点汇总