7-算术逻辑运算指令

一、乘除运算指令

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

(1)无符号数乘法指令

名称 MUL(无符号乘法指令)
格式 MUL OPRD
动作 乘数是OPRD,被乘数位于AL、AX或EAX中(由OPRD的尺寸决定,乘数和被乘数的尺寸一致),相乘后乘积尺寸翻倍:16位乘积送到AX;32位乘积送DX:AX;64位乘积送EDX:EAX
合法值 OPRD:通用寄存器、存储单元
注意 OPRD不能是立即数
乘数和被乘数的尺寸一致
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不能是立即数
乘数和被乘数的尺寸一致
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尺寸不能超过目的操作数
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不能是立即数
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
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
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。
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
MOV   EAX, 12563487H   ;EAX=12563487H
CDQ                    ;EDX=00000000H, EAX=12563487H

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

#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位
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位
MOV    DX, 8885H             ;DX=8885H
MOVZX  ECX, DL               ;ECX=00000085H
MOVZX  EAX, DX               ;EAX=00008885H

综合示例

//参数是有符号字符型,返回值是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
//参数是无符号字符型,返回值是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:通用寄存器、存储单元
NOT   CL
NOT   EAX
NOT   BX

(2)与运算指令

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

(3)或运算指令

名称 OR(或运算指令)
格式 OR DEST,SRC
动作 指令对两个操作数进行按位的逻辑或运算,结果送到目的操作数DEST
合法值 SRC:通用寄存器、存储单元、立即数
OPRD:通用寄存器、存储单元
注意 两个操作数最多只能有一个是存储单元
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:通用寄存器、存储单元
注意 两个操作数最多只能有一个是存储单元
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
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示例

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
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示例

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

循环移位指令的示例

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之间

示例

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
posted @ 2025-10-23 14:44  pridelzh  阅读(3)  评论(0)    收藏  举报