算术运算
符号扩展
符号扩展:用一个操作数的符号位(即最高位)形成另一个操作数
结果:后一个操作数各位是0(正数)或者是1(负数)
符号扩展不改变数据大小
将字节转换成字指令
语句格式:
CBW(convert byte to word)
功能: 将AL中的符号扩展至AH中, 操作数是隐含且固定的
将字转换成双字指令
语句格式:
CWD
功能: 将AX中的符号扩展至DX中, 操作数是隐含且固定的
比较指令CMP
格式:CMP OPD,OPS
功能:(OPD) — (OPS)
说明:目的操作数减去源操作数,然后根据结果设置标志位,但该结果并不存入目的地址
影响标志位: AF、CF、OF、PF、SF 、 ZF
作用: 一般的后面跟一条条件转移指令,根据比较结果转向不同的程序分支,用于处理OPD
和OPS
大小比较的不同情况
逻辑运算
逻辑与
AND
指令的格式
AND Reg/Mem, Reg/Mem/Imm
受影响的标志位 CF(0)、OF(0)、PF、SF和ZF
(AF无定义)
逻辑或
OR
指令的格式
OR Reg/Mem, Reg/Mem/Imm
受影响的标志位 CF(0)、OF(0)、PF、SF和ZF
(AF无定义)
逻辑非
NOT
指令的格式
NOT Reg/Mem
受影响的标志位:无
异或
XOR
指令的格式
XOR Reg/Mem, Reg/Mem/Imm
受影响的标志位 CF(0)、OF(0)、PF、SF和ZF
(AF无定义)
TEST
格式
TEST Reg/Mem, Reg/Mem/Imm
作用
执行AND
,但是不影响目标操作数
受影响的标志位 CF(0)、OF(0)、PF、SF和ZF
(AF无定义)。
Eg: test ax, ax
// ax 为0, 则ZF = 0
// ax 不为0,则ZF = 1
技巧
- 如果要将目的操作数中某些位清0,用AND,称之为屏蔽
- 如果要将目的操作数中某些位置1,用OR
- 用来测试目的操作数中某一位或某几位是否为0或1,而目的操作数不变,TEST,
- TEST与CMP的区别,前者是测试一位或几位,后者测试整个字节/字/双字是否相等
- 操作数自身相或、相与结果不变。
- XOR AX,AX 将AX置0,比mov ax,0 更高效。
算术运算指令
加减乘除
加法
add
加法 可能产生溢出- 相关的标志位是
CF
adc
加法会计算当前CF
add
ADD reg,imm/reg/mem
;reg←reg+imm/reg/mem
ADD mem,imm/reg
;mem←mem+imm/reg
adc
ADC reg,imm/reg/mem
;reg←reg+imm/reg/mem+CF
ADC mem,imm/reg
;mem←mem+imm/reg+CF
inc
inc: 加一,不影响CF标志位
inc ax
大数运算
编写汇编指令计算加法:
$7654 3218 + fa23 fbc3 = 1 7078 2DDB$
赋值:
mov ax,3218
mov bx,7654
运算:
add ax,fbc3//加法
adc bx,fa23//加法,考虑进位
结果:
CF [bx] [ax]
1 7078 2DDB
减法
sub
减法 可能产生借位- 相关的标志位是
CF
sbb
减法会计算当前CF
sub
SUB reg,imm/reg/mem
;reg←reg-imm/reg/mem
SUB mem,imm/reg
;mem←mem-imm/reg
sbb
SBB reg,imm/reg/mem
;reg←(reg-(imm/reg/mem)-CF)
SBB mem,imm/reg
;mem←mem-imm/reg-CF
dec
dec: -1,不影响CF位
dec ax
大数运算
$7078 2DDB- 7654 3218= FA23 FBC3$
赋值:
mov ax,2DDB
mov bx,7078
运算:
sub ax,3218
sbb bx,7654
结果:
CF [bx] [ax]
1 FA23 FBC3
乘法
无符号乘法
格式:MUL Reg/Mem
功能:显式操作数*隐含操作数(看成无符号数)
影响标志位:CF和OF
位数 | 隐含的被乘数 | 乘积的存放位置 | 举例 |
---|---|---|---|
8 | AL | AX | MUL BL |
16 | AX | DX-AX | MUL BX |
32 | EAX | EDX-EAX | MUL ECX |
无符号乘法影响标志位
- 如果乘积的高一半位(
AH/DX/EDX
) 包含有乘积的有效位
则CF=1、OF=1
否则CF=0,OF=0
OF=CF=1则说明:
- 字节*字节结果超过了8位
- 字*字节结果超过了16位
- 双字*双字结果超过了32位
有符号乘法
格式:
IMUL Reg/Mem
IMUL Reg, Imm ;80286+
IMUL Reg, Reg, Imm ;80286+
IMUL Reg, Reg/Mem ;80386+
功能: 有符号数相乘
影响标志位: CF和OF
有符号乘法影响标志位
- 如果乘积的高一半位(AH,DX,EDX)不是低位的符号扩展
则CF=1、OF=1
否则,CF=0,OF=0
举例:
al = 03H, bl = 40H$
imul bl
除法
无符号除法
格式:
DIV Reg/Mem
位数 | 被除数 | 被除数 | 除数 | 余数 |
---|---|---|---|---|
8 | AX | 8 bit ops | AL | AH |
16 | DX,AX | 16 bit ops | AX | DX |
32 | EDX,EAX | 32 bit ops | EAX | EDX |
影响标志位:未定义
未定义:指令执行后这些标志是任意的,不可预测的
没有影响:指令执行后不改变标志状态
有符号除法
格式:
IDIV Reg/Mem
位数 | 被除数 | 被除数 | 除数 | 余数 |
---|---|---|---|---|
8 | AX | 8 bit ops | AL | AH |
16 | DX,AX | 16 bit ops | AX | DX |
32 | EDX,EAX | 32 bit ops | EAX | EDX |
影响标志位:AF、CF、OF、PF、SF和ZF
除法溢出
- 被除数远大于除数时,所得的商就有可能超出它所能表达的范围
- idiv除法溢出
字节除时商不在-128~127范围内,或者在字除时商不在-32768~32767范围内 div除法溢出
8位除法运算结果大于8位,16位除法运算结果大于16位
举例:ax = FFFF bl = FF div bl
结果:
相当于FFFF / FF = 101
此时AH显然放不下,所以商溢出了
求补指令 NEG
- NEG指令对操作数执行求补运算: 用零减去操作数,然后结果返回操作数
- 求补运算也可以表达成: 将操作数按位取反后加1
neg ax
;如果ax = 0
,则CF标志位 = 0
;若ax != 0
, 则CF = 1
neg ax
三目运算 无分支
求通解:
Reg == a ? b : b-1
要求:
不使用分支实现 运算
我们把操作数 给ax
Reg == 0 ? 0 : -1
解:
mov ax, 3
neg ax //不为0就会影响CF
sbb ax,ax //ax=ax-ax-CF
Reg == 6 ? 0 : -1
解:
mov ax,3 //给测试值
sub ax,6
neg ax
sbb ax,ax
add ax,0
Reg == 6 ? 9 : 8
解:
mov ax,3
sub ax,6
neg ax
sbb ax,ax
add ax,9
Reg == a ? b : b-1
解:
mov ax,3
sub ax,a
neg ax
sbb ax,ax
add ax,b
求通解:
Reg == a ? b-1 : b
要求:
不使用分支实现 运算
我们把操作数 给ax
Reg == 0 ? -1 :0
解:
mov ax,3
neg ax
mov ax,0
adc ax,-1
Reg == a ? -1 : 0
解:
mov ax,3
sub ax,a
neg ax
mov ax,0
adc ax,-1
Reg == 6 ? 8 : 9
解:
mov ax,3
sub ax,6
neg ax
mov ax,0
adc ax,-1
add ax,9
Reg == a ? b-1 : b
解:
mov ax,3
sub ax,a
neg ax
mov ax,0
adc ax,-1
add ax,b
求通解:
Reg == a ? b : c
Reg == 8 ? 3 : 13
mov ax,9
sub ax,a
neg ax
sbb ax,ax
and ax,c-b
add ax,b