7-算术逻辑运算指令

一、乘除运算指令

  • 乘除运算指令区分有符号数与无符号数
  • 对状态标志的影响,和加减指令相比不是很自然。

(1)无符号数乘法指令

名称 MUL(无符号乘法指令)
格式 MUL OPRD
动作 乘数是OPRD,被乘数位于AL、AX或EAX中(由OPRD的尺寸决定,乘数和被乘数的尺寸一致),相乘后乘积尺寸翻倍:16位乘积送到AX;32位乘积送DX:AX;64位乘积送EDX:EAX
合法值 OPRD:通用寄存器、存储单元
注意 OPRD不能是立即数
乘数和被乘数的尺寸一致
1
2
3
MUL   BL                 //8位乘    乘积在AX
MUL ECX //32位乘 乘积在DX:AX
MUL DX //16位乘 乘积在EDX:EAX

(1)有符号数乘法指令

  1. 单操作数形式:
名称 IMUL(单操作数乘法指令)
格式 IMUL OPRD
动作 乘数是OPRD,被乘数位于AL、AX或EAX中(由OPRD的尺寸决定,乘数和被乘数的尺寸一致),乘法运算时把二者看作有符号数,相乘后乘积尺寸翻倍:16位乘积送到AX;32位乘积送DX:AX;64位乘积送EDX:EAX
合法值 OPRD:通用寄存器、存储单元
注意 OPRD不能是立即数
乘数和被乘数的尺寸一致
1
2
IMUL   CL
IMUL DWORD PTR [EBP+12] //双字存储单元
  1. 双操作数形式:
名称 IMUL(双操作数乘法指令)
格式 IMUL DEST,SRC
动作 DEST和SRC相乘后送到DEST,乘法运算时把二者看作有符号数
合法值 DEST:16位或者32位通用寄存器
SRC:通用寄存器、存储单元、立即数
注意 DEST不能是8位寄存器
SRC是通用寄存器、存储单元时,尺寸需要和目的操作数一致
SRC是立即数时,尺寸不能超过目的操作数
  1. 三操作数形式:和MUL相比
名称 IMUL(三操作数乘法指令)
格式 IMUL DEST,SRC1,SRC2
动作 SRC1 和SRC2相乘后送到DEST,乘法运算时把二者看作有符号数
合法值 SRC1:寄存器、存储单元
SRC2:立即数
注意 SRC1和SRC2都看作有符号数
SRC1尺寸需要和目的操作数一致
SRC2尺寸不能超过目的操作数
1
2
3
4
5
6
IMUL   BX
IMUL EBX, ECX
IMUL AX,CX,3
IMUL EDX,DWORD PTR [ESI],5
IMUL AX,7
IMUL AX,AX,7

(3)无符号数除法指令

名称 DIV(无符号数除法指令)
格式 DIV OPRD
动作 除数是OPRD
被除数位于AX、DX:AX或EDX:EAX中(被除数的尺寸是OPRD两倍
商在AL、AX或者EAX中(尺寸与oprd相同
余数在AH、DX或者EDX中(尺寸与oprd相同
合法值 OPRD:寄存器、存储单元
注意 必须防止除溢出,除数不能为0商不能太大超出存放位置尺寸
OPDR不能是立即数
1
2
3
DIV   BL                //除数8位
DIV ESI //除数32位
DIV CX //除数16位

(4)有符号数除法指令

名称 IDIV(有符号数除法指令)
格式 IDIV OPRD
动作 除数是OPRD
被除数位于AX、DX:AX或EDX:EAX中(尺寸为OPRD两倍
商在AL、AX或者EAX中(尺寸同OPRD
余数在AH、DX或者EDX中(尺寸同OPRD
合法值 OPRD:寄存器、存储单元
注意 必须防止除溢出,除数不能为0商绝对值不能太大超出存放位置尺寸
如果不能整除,余数的符号与被除数一致,而且余数的绝对值小于除数的绝对值。
OPDR不能是立即数

(5)符号扩展指令

  1. 字节转换为字
名称 CBW(字节转换为字指令)
格式 CBW
动作 指令把AL中的符号扩展到AH
注意 若AL的最高有效位为0,则AH=0;若AL的最高有效位为1,则AH=0FFH,也即AH的8位全都为1
1
2
3
4
MOV   AX, 3487H        //AX=3487H
CBW //AX=FF87H
MOV AX, 8734H
CBW //AX=0034H
  1. 字转换为双字
名称 CWD(字转换为双字指令)
格式 CWD
动作 指令把AX中的符号扩展到DX
注意 若AX的最高有效位为0,则DX=0;若AX最高有效位为1,则DX=0FFFFH,也即DX的16位全都为1
1
2
3
4
MOV   AX, 3487H        //AX=3487H
CWD //DX=0000H, AX=3487H
MOV AX, 8734H
CWD //DX=FFFFH, AX=8734H
名称 CWDE(字转换为双字指令)
格式 CWDE
动作 指令把AX中的符号扩展到EAX高16位
注意 AX的最高有效位为0,则EAX的高16位都为0;若AX的最高有效位为1,则EAX的高16位都为1。
1
2
3
4
MOV   AX, 3487H        //AX=3487H
CWDE //EAX=00003487H
MOV AX, 8734H
CWDE //EAX=FFFF8734H
  1. 双字转换为四字
名称 CDQ(双字转换为四字指令)
格式 CDQ
动作 指令把EAX中的符号扩展到EDX
注意 若EAX的最高有效位为0,则DX=0;若AX最高有效位为1,则DX=0FFFFFFFFH,也即EDX的16位全都为1
1
2
MOV   EAX, 12563487H   ;EAX=12563487H
CDQ ;EDX=00000000H, EAX=12563487H

综合示例:演示除法指令和符号扩展指令的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include  <stdio.h>
int main()
{
int quotient, remainder; //为了输出结果,安排两个变量
_asm
{
MOV AX, -601
MOV BL, 10
IDIV BL //除数是BL,被除数是AX,余数在AH,商在AL
MOV BL, AH //先临时保存余数
;
CBW //商在AL,符号扩展到AX
CWDE //AX符号扩展到EAX
MOV quotient, EAX
;
MOV AL, BL //余数送到AL
CBW //AL符号扩展到AX
CWDE //AX符号扩展到EAX
MOV remainder, EAX
}
printf("quotient= %d\n", quotient); //显示为-200
printf("remainder= %d\n", remainder); //显示为-1
return 0;
}
  1. 符号扩展传送指令
名称 MOVSX(符号扩展传送指令指令)
格式 MOVSX DEST,SRC
动作 把源操作数符号扩展后送至目的操作数DEST
合法值 SRC:通用寄存器、存储单元
DEST:通用寄存器
注意 目的操作数的尺寸必须大于源操作数的尺寸。源操作数的尺寸可以是8位或者16位;目的操作数的尺寸可以是16位或者32位
1
2
3
4
5
MOV    AL, 85H               //AL=85H
MOVSX EDX, AL //EDX=FFFFFF85H
MOVSX CX, AL //CX=FF85H
MOV AL, 75H //AL=75H
MOVSX EAX, AL //EAX=00000075H
  1. 零扩展传送指令
名称 MOVZX(零扩展传送指令指令)
格式 MOVZX DEST,SRC
动作 指令把源操作数SRC零扩展后送至目的操作数DEST
合法值 SRC:通用寄存器、存储单元
DEST:通用寄存器
注意 目的操作数的尺寸必须大于源操作数的尺寸。源操作数的尺寸可以是8位或者16位;目的操作数的尺寸可以是16位或者32位
1
2
3
MOV    DX, 8885H             ;DX=8885H
MOVZX ECX, DL ;ECX=00000085H
MOVZX EAX, DX ;EAX=00008885H

综合示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//参数是有符号字符型,返回值是int
int cf310(char x, char y)
{
return ( x + 22 ) / y ;
}

//转汇编如下
push ebp
mov ebp, esp
movsx eax, BYTE PTR [ebp+8] //把参数x符号扩展后送到eax
add eax, 22
movsx ecx, BYTE PTR [ebp+12] //把参数y符号扩展后送到ecx
cdq //符号扩展,形成64位的被除数
idiv ecx
pop ebp
ret
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//参数是无符号字符型,返回值是unsigned int
unsigned int cf311(unsigned char x, unsigned char y)
{
return (unsigned)( x + 22 ) / y ;
}

//转汇编如下
push ebp
mov ebp, esp
movzx eax, BYTE PTR [ebp+8] //把参数x零扩展后送到eax
add eax, 22
movzx ecx, BYTE PTR [ebp+12] //把参数x零扩展后送到ecx
xor edx, edx //零扩展,形成64位的被除数
div ecx
pop ebp
ret

二、逻辑运算指令

  • C语言中有一组按位逻辑运算符
    1. 按位取反运算符 ~
    2. 按位与运算符 &
    3. 按位或运算符 |
    4. 按位异或运算符 ^
  • 处理器提供一组逻辑运算指令
    1. 否指令 NOT
    2. 与指令 AND
    3. 或指令 OR
    4. 异或指令 XOR
  • 关于逻辑运算指令的通用说明
    1. 只有通用寄存器或存储单元可作为目的操作数,用于存放运算结果。
    2. 如只有一个操作数,则该操作数既是源又是目的。
    3. 如有两个操作数,那么最多只能有一个是存储单元源操作数可以是立即数
    4. 存储单元可采用各种存储器操作数寻址方式。
    5. 操作数可以是字节、字或者双字。如果有两个操作数,尺寸必须一致

(1)否运算指令

名称 NOT(否运算指令)
格式 NOT OPRD
动作 把操作数OPRD按位取反,然后送回OPRD
合法值 OPRD:通用寄存器、存储单元
1
2
3
NOT   CL
NOT EAX
NOT BX

(2)与运算指令

名称 AND(与运算指令)
格式 AND DEST,SRC
动作 指令对两个操作数进行按位的逻辑与运算,结果送到目的操作数DEST
合法值 SRC:通用寄存器、存储单元、立即数
OPRD:通用寄存器、存储单元
注意 两个操作数最多只能有一个是存储单元
1
2
3
AND   ECX,ESI
MOV AX,3437H //AX=3437H
AND AX,0F0FH //AX=0407H

(3)或运算指令

名称 OR(或运算指令)
格式 OR DEST,SRC
动作 指令对两个操作数进行按位的逻辑或运算,结果送到目的操作数DEST
合法值 SRC:通用寄存器、存储单元、立即数
OPRD:通用寄存器、存储单元
注意 两个操作数最多只能有一个是存储单元
1
2
3
4
OR    CL,CH
OR EBX,EAX
MOV AL,41H ;AL=01000001B,后缀B表示二进制
OR AL,20H ;AL=01100001B

(4)异或运算指令

名称 XOR(异或运算指令)
格式 XOR DEST,SRC
动作 指令对两个操作数进行按位异或的逻辑“异或”运算,结果送到目的操作数DEST
合法值 SRC:通用寄存器、存储单元、立即数
OPRD:通用寄存器、存储单元
注意 两个操作数最多只能有一个是存储单元
1
2
3
4
MOV   AL,34H         ;AL=00110100B,符号B表示二进制
MOV BL,0FH ;BL=00001111B
XOR AL,BL ;AL=00111011B
XOR ECX,ECX ;ECX=0,CF=0

(5)测试指令

名称 TEST(测试指令)
格式 TEST DEST,SRC
动作 类似指令AND,把两个操作数进行按位“与”,但结果不送到目的操作数DEST,仅仅影响状态标志
合法值 SRC:通用寄存器、存储单元、立即数
OPRD:通用寄存器、存储单元
注意 两个操作数最多只能有一个是存储单元
标志ZF、PF和SF反映运算结果,标志CF和OF被清0
1
2
3
4
5
6
TEST  AL, BL
TEST EDX, ECX

//检查AL中的位6和位2是否有一位为1
TEST AL,01000100B //符号B表示二进制
//随后,判断标志位ZF,若ZF=0,则这两位上都是0

三、移位指令

关于移位的几个要素:

  1. 移动方式
    • 一般移位指令
    • 循环移位指令
    • 双精度移位指令
  2. 移动方向
    • 左移
    • 右移
  3. 移动位数
    • 1位
    • m位

(1)一般移位指令

名称 算术左移SAL SAL OPRD,count
逻辑左移SHL SHL OPRD,count
算术右移SAR SAR OPRD,count
逻辑右移SHR SHR OPRD,count
动作 算术左移SAL:动作一样,左移count位。每左移一位,移出的最高位进入CF,最低位补0
逻辑左移SHL:同算术左移SAL
算术右移SAR:右移count位。每右移一位,移出的最低位进入CF,符号(最高)位不变
逻辑右移SAR:右移count位。每右移一位,移出的最低位进入CF,符号(最高)位补0
合法值 count:8位立即数、存储单元、寄存器CL
OPRD:通用寄存器、存储单元(字节、字、双字)
注意 通过截取count的低5位,实际的移位数被限于0到31之间

1747106285619.webp

SAL、SHL示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MOV   EBX, 7400EF9CH    //EBX=7400EF9CH
ADD EBX, 0 //EBX=7400EF9CH,CF=0,SF=0,ZF=0,PF=1
SHL EBX, 1 //EBX=E801DF38H,CF=0,SF=1,ZF=0,PF=0
MOV CL, 3 //CL=3
SHL EBX, CL //EBX=400EF9C0H,CF=1,SF=0,ZF=0,PF=1
SHL EBX, 16 //EBX=F9C00000H,CF=0,SF=1,ZF=0,PF=1
SHL EBX, 12 //EBX=00000000H,CF=0,SF=0,ZF=1,PF=1

//实现把寄存器AL中的内容(设为无符号数)乘以10
//算术(逻辑)左移1位,相当于乘以2
XOR AH, AH //AH=0
SHL AX, 1 //2*X
MOV BX, AX //暂存2*X
SHL AX, 2 //8*X
ADD AX, BX //8*X+2*X

SAR示例

1
2
3
4
5
6
//算术右移1位,相当于有符号数除以2
MOV DX, 82C3H //DX=82C3H
SAR DX, 1 //DX=C161H,CF=1,SF=1,ZF=0,PF=0
MOV CL, 3 //CL=3
SAR DX, CL //DX=F82CH,CF=0,SF=1,ZF=0,PF=0
SAR DX, 4 //DX=FF82H,CF=1,SF=1,ZF=0,PF=1

SHR示例

1
2
3
4
5
MOV   DX, 82C3H         //DX=82C3H
SHR DX, 1 //DX=4161H,CF=1,SF=0,ZF=0,PF=0
MOV CL, 3 //CL=3
SHR DX, CL //DX=082CH,CF=0,SF=0,ZF=0,PF=0
SHR DX, 12 //DX=0000H,CF=1,SF=0,ZF=1,PF=1

(2)循环移位指令

名称 左循环移位指令 ROL ROL OPRD,count
右循环移位指令 ROR ROR OPRD,count
带进位左循环移位指令 RCL RCL OPRD,count
带进位右循环移位指令 RCR RCR OPRD,count
动作 见下图
合法值 count:8位立即数、存储单元、寄存器CL
OPRD:通用寄存器、存储单元(字节、字、双字)
注意 通过截取count的低5位,实际的移位数被限于0到31之间

1747106441546.webp

循环移位指令的示例

1
2
3
4
5
6
7
8
9
MOV   DX, 82C3H           ;DX=82C3H
ROL DX, 1 ;DX=0587H, CF=1
MOV CL, 3 ;CL=3
ROL DX, CL ;DX=2C38H, CF=0
MOV EBX, 8A2035F7H ;EBX=8A2035F7H
ROR EBX, 4 ;EBX=78A2035FH, CF=0
STC ;CF=1(设置进位标志)
RCL EBX, 1 ;EBX=F14406BFH, CF=0
RCR EBX, CL ;EBX=DE2880D7H, CF=1

(3)双精度移位指令

  • 把一个操作数的部分内容移位方式复制到另一个操作数
名称 双精度左移SHLD SHLD OPRD1,OPRD2,count
双精度右移SHRD SHRD OPRD1,OPRD2,count
动作 双精度左移SHLD :OPDR1左移count位,低端空出的位用OPDR2高端的count位填补,但OPDR2不变。OPDR1中最后移出的放在CF
双精度右移SHRD :OPDR1右移count位,高端空出的位用OPDR2低端的count位填补,但OPDR2不变。OPDR1中最后移出的放在CF
合法值 OPDR1:通用寄存器、存储单元(字、双字)
OPRD:通用寄存器(字、双字)
注意 两个操作数尺寸必须一致
count表示移位的位数,可以是一个8位立即数,也可以是寄存器CL。寄存器CL表示移位数由CL的值决定。通过截取count的低5位,移位数被限于0到31之间

示例

1
2
3
4
5
6
7
8
9
10
MOV   AX, 8321H
MOV DX, 5678H
SHLD AX, DX, 1 //AX=0642H,DX=5678H,CF=1,OF=1
SHLD AX, DX, 2 //AX=1909H,DX=5678H,CF=0,OF=0

MOV EAX, 01234867H
MOV EDX, 5ABCDEF9H
SHRD EAX, EDX, 4 //EAX=90123486H,CF=0,OF=1
MOV CL, 8
SHRD EAX, EDX, CL //EAX=F9901234H,CF=1,OF=0