`
isiqi
  • 浏览: 16004862 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

汇编语言与微机接口学习笔记(五)运算指令

阅读更多

算术运算指令
对于算术指令中的双操作数指令,其两个操作数寻址方式的限定同MOV指令,即目标操作数不允许是立即数和CS段寄存器,两个操作数不能同时为存储器操作数等。

二进制算术运算指令
参与运算的操作数及计算结果都是8位、16位或32位无符号或带符号二进制数(在书写指令时可以用十进制形式表示,但经汇编后将成为二进制形式)。
带符号数在机器中用补码形式表示,最高位为符号位。

类型转换指令
这类指令实际上是把操作数的最高位进行扩展,用于处理带符号数运算的操作数类型匹配问题。
① 字节扩展成字指令CBW(Convert Byte to Word)
格式:CBW
功能:把AL寄存器中的符号位值扩展到AH中。
例: MOV AL , 5
CBW ;(AH)= 0,AL值不变
MOV AL , 80H
CBW ;(AH)= 0FFH,AL值不变
② 字扩展成双字指令CWD(Convert Word to Doubleword)
格式:CWD
功能:把AX寄存器中的符号位值扩展到DX中。
例: MOV AX , 5
CWD ;(DX)= 0,AX值不变
MOV AX , 9098H
CWD ;(DX)= 0FFFFH,AX值不变
③ 双字扩展成四字指令CDQ(Convert Doubleword to
Quad-Word)
格式:CDQ
功能:把EAX寄存器中的符号位值扩展到EDX中。
说明:80386以上CPU支持。
④ AX符号位扩展到EAX指令CWDE(Convert Word to
Doubleword Extended)
格式:CWDE
功能:把AX寄存器中的符号位值扩展到EAX的高16位。
说明:80386以上CPU支持。

二进制加法指令
这类指令中的每一条均适合于带符号数和无符号数运算。
① 加法指令ADD( Add)
格式:ADD DST , SRC
功能:(DST)+(SRC)→ DST
说明:对操作数的限定同MOV指令。
标志:影响OF、SF、ZF、AF、PF、CF标志
例: ADD AX , 35
ADD WORD PTR [BX] , 56
② 带进位加法指令ADC( Add with carry)
格式:ADC DST , SRC
功能:(DST)+(SRC) + CF→ DST
说明:由于考虑CF,所以可用于多字节或多字加法。
标志:影响OF、SF、ZF、AF、PF、CF标志
③ 加1指令INC( Increment)
格式:INC DST
功能:(DST)+ 1→ DST
说明:可以很方便地实现地址指针或循环次数的加1。
标志:影响OF、SF、ZF、AF、PF标志
例: INC BX
④ 交换并相加指令XADD( Exchange and Add)
格式:XADD DST,SRC
功能:(DST)+(SRC)→TEMP、(DST)→SRC、
TEMP→DST
说明:该指令执行后,原DST的内容在SRC中,和在DST
中。80486以上CPU支持。
标志:影响OF、SF、ZF、AF、PF、CF标志
条件标志(条件码)位中最主要的是CF,ZF,SF,OF四位,分别表示进位、结果为0、符号和溢出的情况。其中ZF和SF的设置比较简单。这里将主要分析CF和OF位的设置情况。
对于两个二进制数进行加法运算:无符号数相加结果若使CF置1,则表示溢出;带符号数相加结果若使OF置1,则表示溢出。一旦发生溢出,结果就不正确了。
执行加法指令时,CF位是根据最高有效位是否有向高位的进位设置的。OF位则根据操作数的符号及其变化情况来设置。若两个操作数符号相同,而结果的符号与之相反时OF=1。

二进制减法指令
这类指令中的每一条均适合于带符号数和无符号数运算。
① 减法指令SUB( Subtract)
格式:SUB DST , SRC
功能:(DST)-(SRC)→ DST
说明:除是实现减法功能外,其它要求同ADD。
标志:影响OF、SF、ZF、AF、PF、CF标志
例: SUB AX , 35
SUB WORD PTR [BX] , 56
② 带借位减法指令SBB( Subtract with Borrow)
格式:SBB DST , SRC
功能:(DST)-(SRC) - CF → DST
说明:由于考虑CF,所以可用于多字节或多字减法。
标志:影响OF、SF、ZF、AF、PF、CF标志
③ 减1指令DEC( Decrement)
格式:DEC DST
功能: (DST)- 1→ DST
说明:可以很方便地实现地址指针或循环次数的减1修
改。
标志:影响OF、SF、ZF、AF、PF标志
④ 比较指令CMP( Compare)
格式:CMP DST , SRC
功能: (DST)- (SRC),影响标志位
说明:这条指令执行相减操作后只根据结果设置标志
位,并不改变两个操作数的原值。CMP指令后往往跟着
一条条件转移指令,根据比较结果产生不同的程序分支。
标志:影响OF、SF、ZF、AF、PF、CF标志
⑤ 求补指令NEG( Negate)
格式:NEG DST
功能:对目标操作数(含符号位)求反加1,即实现
0-(DST)→DST。
说明:可用来求一个数的相反数。
标志:影响OF、SF、ZF、AF、PF、CF标志。
例: EAX中存放一负数,求该数的绝对值。
NEG EAX
减法指令执行后若使CF=1,则对无符号数而言发生了溢出。若使OF=1,则对带符号数而言发生了溢出。

加法、减法指令综合举例
例1:试编写两个三字节长的二进制数加法程序,加数FIRST、SECOND及和SUM的分配情况如下页图所示。
程序代码:
LEA DI,SUM ;建立和的地址指针DI
ADD DI,2 ;DI指向和的低字节
MOV BX,2
MOV AL,FIRST[BX] ;取FIRST的低字节(本例为33H)
ADD AL,SECOND+2 ;两个低字节相加,和①在AL中,进位反映在CF中
MOV [DI],AL ;把低字节和存到DI指向的单元(本例为SUM+2单元)
DEC DI ;修改和指针,使其指向中字节
DEC BX ;修改加数指针,使其指向中字节
MOV AL,FIRST[BX] ;取FIRST的中字节(本例为22H)
ADC AL,SECOND+1 ;两个中字节相加且加CF,和②在AL中,进位反映在CF中
MOV [DI],AL ;把中字节和存到DI指向的单元(本例为SUM+1单元)
DEC DI ;修改和指针,使其指向高字节
DEC BX ;修改加数指针,使其指向高字节
MOV AL,FIRST[BX] ;取FIRST的高字节(本例为11H)
ADC AL,SECOND ;两个高字节相加且加CF,和③在AL中,进位反映在CF中
MOV [DI],AL ;把高字节和存到DI指向的单元(本例为SUM单元)
注意:
1. DEC DI和SUB DI , 1指令不可互换。因为上一条加法指令对CF的影响后边要用到,所以不能破坏CF值,使用DEC指令正好不影响CF。
2. 多字节或多字加减时,CF始终有意义(前边的反映进位或借位,最后一次反映溢出情况),而OF只有最后一次的才有意义。

二进制乘法指令
系统对无符号数和带符号数各提供一条二进制乘法指令。
① 无符号乘法指令MUL( Unsigned Multiple)
格式:
说明:必须注意这个源操作数只能是寄存器(reg)或存储器操作数(m),不能是立即数。另一个乘数必须事前放在累加器中。可以实现8位、16位、32位无符号数乘。
MUL SRC reg/m
执行操作:
字节操作数: (AX)← (AL)×(SRC)
字操作数: (DX, AX)←(AX)×(SRC)
双字操作数: (EDX, EAX)← (EAX )× (SRC)
标志:只有CF、OF有意义,其它标志不确定。若乘积的高半部分(例字节型乘法结果的AH)为0则对CF和OF清0,否则置CF和OF为1。
例:
MOV AL , 8
MUL BL ;(AL)×(BL),结果在AX中
MOV AX , 1234H
MUL WORD PTR [BX]
;(AX)×([BX]),结果在DX:AX中
② 带符号乘法指令IMUL( Signed Multiple)
格式1:
说明:除了是实现两个带符号数相乘外,其它与MUL指令相同。
IMUL SRC reg/m
标志:只有CF、OF有意义,其它标志不确定。若乘积的高半部分(例字节型乘法结果的AH)为低半部分的符号扩展,则对CF和OF清0,否则置CF和OF为1。
例: MOV AL , 80H
CBW
IMUL BX ;(AX)×(BX),结果在DX:AX中
注:以下格式只对80286以上CPU有效。
格式2:
IMUL REG,SRC reg/m
说明: REG和SRC的长度必须相同,目标操作数REG必须是16位或32位通用寄存器。
执行操作:
(REG)16 <- (REG)16 * (SRC)16
(REG)32 <- (REG)32 * (SRC)32
标志:只有CF、OF有意义,其它标志不确定。若乘积完全能放入目标寄存器,则对CF和OF清0,否则置CF和OF为1(OF为1说明溢出)。
例: IMUL CX , WORD PTR [BX] ;(CX)×([BX]),结果在CX中
格式3:IMUL REG,imm8
说明:源操作数imm8只能是8位立即数,计算时系统自动对其进行符号扩展。
执行操作:
(REG)16 <- (REG)16 * imm8符号扩展
(REG)32 <- (REG)32 * imm8符号扩展
标志:对标志位的影响同格式2。
例: IMUL CX , 98H ;(CX)×0FF98H,结果在CX中
格式4:IMUL REG,SRC reg/m,imm8
执行操作:
(REG)16 <- (SRC)16*imm8符号扩展
(REG)32 <- (SRC)32*imm8符号扩展
标志:对标志位的影响同格式2。
例: IMUL CX , BX , 98H ;(BX)×0FF98H,结果在CX中

二进制除法指令
系统对无符号数和带符号数各提供一条二进制除法指令。
① 无符号除法指令DIV( Unsigned Divide)
格式:DIV SRC reg/m
说明:该指令只含一个源操作数,该操作数作为除数使用。被除数必须事先放在隐含的寄存器中。可以实现8位、16位、32位无符号数除。
执行操作:
字节型除法:
(AX) / (SRC)8 -> 商:AL 余数:AH
字型除法:
(DX:AX) / (SRC)16 -> 商:AX 余数:DX
双字型除法:
(EDX:EAX) / (SRC)32 -> 商:EAX 余数:EDX
标志:不确定。
例:实现1000÷512的无符号数除法。
MOV AX , 1000
SUB DX , DX ; 清0 DX
MOV BX , 512
DIV BX; (DX : AX)÷(BX),商在AX中,余数在DX中
② 带符号除法指令IDIV( Signed Divide)
格式:IDIV SRC reg/m
说明:商和余数均为带符号数、余数符号与被除数相
同。
标志:不确定。
例:实现1000÷(-512)的带符号数除法。
MOV AX , 1000
CWD ; AX符号扩展至DX
MOV BX , -512
IDIV BX ; (DX : AX)÷(BX),商在AX中,余数在DX中
注意:若除数为0或商超出操作数所表示的范围会产生除法错中断,此时系统直接进入0号中断处理程序,为避免出现这种情况,必要时在程序中应事先对操作数进行判断。


十进制调整指令
为了便于十进制数的计算,计算机还提供了一组十进制数调整指令,这组指令在二进制计算的基础上,给予十进制调整,可以直接得到十进制结果。
由于这组指令仅仅是十进制调整而不是真正意义上的十进制运算,所以它们都需要与相应的二进制运算指令配合才可得到正确的十进制结果。使用这组指令时,要注意参与运算的操作数必须是十进制数的编码格式(ASCII码或BCD码)。
80X86的十进制调整指令分为两组:

压缩的BCD码调整指令
① 加法的十进制调整指令DAA( decimal adjust foraddition)
② 减法的十进制调整指令DAS( decimal adjust forsubtraction)

非压缩的BCD码调整指令
① 加法的ASCII调整指令AAA( ASCII adjust for addition)
② 减法的ASCII调整指令AAS( ASCII adjust for subtraction)
③ 乘法的ASCII调整指令AAM( ASCII adjust for multiplication)
④ 除法的ASCII调整指令AAD( ASCII adjust for division)

逻辑指令

逻辑运算指令
NOT DST: 逻辑非指令可用于把操作数的每一位均变反的场合。
AND DST, SRC: 逻辑与指令用于把某位清0(与0相与,也可称为屏蔽某位)、某位保持不变(与1相与)的场合。
TEST OPR1, OPR2: 逻辑测试指令可用于只测试其值而不改变操作数的场合。
OR DST, SRC: 逻辑或指令用于把某位置1(与1相或)、某位保持不变(与0相或)的场合。
XOR DST, SRC: 逻辑异或指令用于把某位变反(与1相异或)、某位保持不变(与0相异或)的场合。
例:设从键盘接收的一个十进制数的ASCII码在AL中,要求把它转换成非压缩BCD码的形式。
AND AL , 0FH ;清0高4位,低4位不变

例:把AL中的非压缩BCD码转换成十进制数的ASCII码形式。
OR AL , 30H ;高4位变成0011B,低4位不变

例:使61H端口的D1位变反。
IN AL , 61H
XOR AL , 2
OUT 61H , AL

例:清0 AX寄存器。
XOR AX , AX
例:测试某一操作数是否与另一确定的操作数相等。
XOR AX , 042EH
JZ MATCH
此操作在检查地址是否匹配时常用。

例:设某并行打印机的状态端口是379H,其D7位是忙闲位:若D7=0表示忙,为1表示闲。测试该打印机当前状态,若为忙继续测试,否则顺序执行下一条指令。
MOV DX , 379H
WT:IN AL , DX
TEST AL , 80H
JZ WT


位测试并修改指令:
从80386开始增加了位测试指令,这些指令首先把指定位的值送给CF标志,然后对该位按照指令的要求操作。
说明:本组指令中,目标可以是16或32位的寄存器或存储器操作数,源可以是8位的立即数、寄存器或存储器操作数。若源操作数不是立即数,其长度一定要和目标的长度相同;若是立即数,则其值不应超过目标操作数的长度。
1.名称:位测试
格式:BT DST, SRC
功能:测试由SRC指定的DST中的位
标志:所选位值送CF,其它标志不定
2.位测试并置位
格式:BTS DST,SRC
功能:测试并置1由SRC指定的DST中的位
标志:同1
3.位测试并复位
格式:BTR DST,SRC
功能:测试并置0由SRC指定的DST中的位
标志:同1
4.位测试并取反
格式:BTC DST,SRC
功能:测试并取反由SRC指定的DST中的位
标志:同1

目标操作数的位偏移从最右边位开始、从0开始计数。

例: BTS AX , 4
该指令测试并置1AX寄存器的D4位。若指令执行前
(AX)=1234H,则指令执行后,(CF) = 1 ,(AX) = 1234H。
若指令执行前(AX)=1224H,则指令执行后,
(CF) = 0,(AX) = 1234H。

位扫描指令
从80386开始增加了位扫描指令,可用于扫描操作数中第一个含1的位。

顺向扫描指令BSF (Bit Scan Forward)
格式: BSF DST , SRC
功能:从右向左扫描源操作数中第一个含1的位,并把扫描到的第一个含1的位号送DST操作数。若源操作数为0,则DST值不确定。
说明: DST和SRC可以是16位或32位的,但长度要相同。DST只能是通用寄存器,SRC不能是立即数。
标志:若SRC = 0,则置ZF = 1;否则清0 ZF。

逆向扫描指令BSR (Bit Scan Reverse)
格式: BSR DST , SRC
功能:从左向右扫描源操作数中第一个含1的位,并把扫描到的第一个含1的位号送DST操作数。

例:设AX中存有图形信息,扫描AX,并仅保留其中最左和最右为1的位各1位。
XOR DX , DX ;清0 DX
BSF CX , AX ;把最右边为1的位号送CX
JZ SHORT DONE ;AX为0转到DONE
BTS DX , CX ;把DX的相应位置1
BSR CX , AX ;把最左边为1的位号送CX
BTS DX , CX ;把DX的相应位置1
DONE: MOV AX , DX ;保存到AX

基本移位指令
这类指令实现对操作数移位,包括SHL(逻辑左移)、SAL(算术左移)、SHR(逻辑右移)和SAR(算术右移)指令。
其中, SHL和SAL指令的功能相同,在机器中实际上它们对应的是同一种操作。
通用命令格式:命令 DST,CNT

移位指令常常用来作乘以2或除以2的操作。其中算术移位指令适用于带符号数运算,SAL用来乘以2,SAR用来除以2;而逻辑移位指令则用于无符号数运算,SHL用来乘以2,SHR用来除以2。使用这种方法比直接用乘除法效率要高得多。
例:设无符号数X在AL中,用移位指令实现X×10的运算。
MOV AH , 0 ;为了保证不溢出,将AL扩展为字
SHL AX , 1 ;求得2X
MOV BX , AX ;暂存2X
MOV CL , 2 ;设置移位次数
SHL AX , CL ;求得8X
ADD AX , BX ;10X=8X+2X

循环移位指令

1.循环左移 ROL
格式:ROL DST,CNT
标志:CF中总是最后移进的位,当CNT=1时,移位使符号位改变则置1 OF*,否则清0,不影响ZF、SF、PF

2.循环右移 ROR
格式:ROR DST,CNT
标志:同1

3.带进位循环左移 RCL
格式:RCL DST,CNT
标志:同1

4.带进位的循环右移 RCR
格式:RCR DST,CNT
标志:同1

例:把CX:BX:AX一组寄存器中的48位数据左移一个二进制位。
SHL AX,1
RCL BX,1
RCL CX,1
在没有溢出的情况下,左边程序实现了2×( CX:BX:AX)→CX:BX:AX的功能。

双精度移位指令
这类指令由80386以上CPU支持。

1.双精度左移指令SHLD
格式: SHLD OPRD1 , OPRD2 , CNT
功能:把操作数OPRD1左移由CNT指定的位(设为n),空出的位用操作数OPRD2高端的n位填充,但OPRD2的内容不变,最后移出的位在进位标志CF中。
说明:OPRD1可以是16或32位的寄存器或存储器操作数,OPRD2只能是与OPRD1长度相同的寄存器操作数,CNT是移位位数,由(MOD32)提供0~31之间的值,可以8位立即数的形式放在指令中,或事先放入CL中,然后由CL指定。

2.双精度右移指令SHRD
格式: SHRD OPRD1 , OPRD2 , CNT
功能:把操作数OPRD1右移由CNT指定的位(设为n),空出的位用操作数OPRD2低端的n位填充,但OPRD2的内容不变,最后移出的位在进位标志CF中。

例: SHLD EBX , ECX , 16
如指令执行前, (EBX) = 12345678H,(ECX) = 13572468H;
则指令执行后, (EBX) = 56781357H,(ECX) = 13572468H, (CF) = 0。

程序控制指令
利用本节提供的指令可以改变程序执行的顺序,控制程序的流向。它们均不影响标志位。

转移指令
*无条件转移指令JMP (Jump)
格式: JMP DST
说明:DST为转移的目标地址(或称转向地址),使用与转移地址有关的寻址方式可以形成目标地址。

下边给出JMP指令的各种格式、功能及示例。
1. 段内转移
这类转移指令只改变IP值,不改变CS值。
① 段内直接短转移
格式: JMP SHORT LABEL
功能:无条件转移到标号(LABEL)处。
说明:标号的地址与当前IP值之差在+127~-128字节
范围内。该指令的一个字节的位移量就在指令中。

例: JMP SHORT B1 ;无条件转移到B1标号处
A1: ADD AX , BX
B1: …
② 段内直接近转移
格式: JMP LABEL 或JMP NEAR PTR LABEL
功能:无条件转移到标号处。
说明:在操作数长度为16位的情况下,可以实现距离当前IP值的±32KB范围之内转移。在操作数长度为32位的情况下,可以实现距离当前EIP值的±2GB范围之内转移。可以转移到段内的任一个位置。

例: JMP B2 ;无条件转移到B2标号处
A2: ADD AX , CX
…… ;距离超出+127字节,但仍在本段内
B2: …

③ 段内间接转移
格式: JMP REG/M
功能:无条件转移。其转向地址在通用寄存器或内存单元中。
说明:通用寄存器或内存单元中放段内偏移量,所以必须是16或32位长。

例: LEA BX , B2
JMP BX
A2: ADD AX , CX

B2: SUB AX , CX

例: VAR DW ?
MOV VAR , OFFSET B2
JMP WORD PTR VAR
A2: ADD AX , CX

B2: SUB AX , CX

2. 段间转移
这类转移指令既改变IP值,也改变CS值。
① 段间直接转移
格式: JMP FAR PTR LABEL
功能:无条件转移到标号处。
说明:标号与JMP指令分别处在不同段中。

例: CODE1 SEGMENT

JMP FAR PTR B3

CODE1 ENDS
CODE2 SEGMENT

B3: SUB AX , BX

CODE2 ENDS

② 段间间接转移
格式: JMP DWORD PTR M
功能:无条件段间转移。
说明:转向地址只能放在内存的双字变量中。
例: VAR DD B3
C1 SEGMENT
…J
MP DWORD PTR VAR

C1 ENDS
C2 SEGMENT

B3: SUB AX,CX

C2 ENDS

对于80386CPU以上的实模式或保护模式环境下的虚拟8086方式的段间无条件转移指令与上类似,把双字长的地址指针送给IP和CS,但是EIP的高16位被清0。

*条件转移指令(Jump if Condition is True)
执行这类指令时通过检测由前边指令已设置的标志位确定是否转移,所以它们通常是跟在影响标志的算术、逻辑运算指令之后。这类指令本身并不影响标志。
通用格式: JCC LABEL
功能:如果条件为真,则转向标号处,否则顺序执行下一条指令。
说明:其中cc为条件,LABEL是要转向的标号。
说明:在8086~80286中,该地址应在与当前IP值的-128~+127范围之内,即只能使用段内直接短转移格式;
但从80386开始,转移范围扩大到了段内任意位置,这就意味着它们还可以使用段内直接近转移格式。


循环指令
循环入口地址(指令中的LABEL)只能在当前IP值的-128~+127范围之内,所以循环指令只能使用段内短转移格式。并且所有循环指令都用CX或ECX(操作数长度为32位时)作为循环次数计数器,都不影响标志。

*循环指令LOOP (Loop)
格式: LOOP LABEL
功能: (CX)-1→CX,若(CX)≠0,则转向标号处执行循环体,否则顺序执行下一条指令。
说明:若操作数长度为32位,则其中的CX应为ECX。在LOOP指令前,应先把循环计数的初始值送给CX(或ECX)。

*相等循环指令LOOPE/LOOPZ (Loop while Equal/Zero)
格式: LOOPE/LOOPZ LABEL
功能: (CX)-1→CX,若(CX)≠0 and ZF=1,则转向标号处执行循环体,否则顺序执行下一条指令。
说明:与LOOP指令相同。该指令常用于比较两个字符串是否相等的情况。

*不等循环指令LOOPNE/LOOPNZ (Loop while Not
Equal / Not Zero)
格式: LOOPNE/LOOPNZ LABEL
功能: (CX)-1→CX,若(CX)≠0 and ZF=0,则转向标号处执行循环体,否则顺序执行下一条指令。
说明:与LOOP指令相同。该指令对在数据块中查找信息很有效,当未找到指定字符时继续查找,找到时退出。

子程序调用与返回指令
为便于模块化程序设计和程序共享,经常把一些相对独立的程序段组织成子程序的形式,当需要实现该子程序功能时,由调用程序(或称为主程序)调用之,当子程序结束后再返回到主程序继续执行。

*子程序调用指令CALL (Call procedure)
格式: CALL DST
功能:调用子程序。执行时先把返回地址压入堆栈,再形成子程序入口地址,最后把控制权交给子程序。
说明:其中DST为子程序名或子程序入口地址,不能使用段内直接寻址方式的SHORT格式。CALL指令的执行结果也是无条件转到标号处,但它与JMP指令不同:前者转移后要返回,所以要保存返回地址,而后者转移后不再返回。以下介绍的是8086/8088的子程序调用指令。
1. 段内调用
执行操作:

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics