IA-32汇编语言笔记(7)—— 算术逻辑运算指令

  • 记录汇编语言课笔记,可能有不正确的地方,欢迎指出
  • 教材《新概念汇编语言》—— 杨季文
  • 这篇文章对应书第二章 IA32处理器基本功能 3.2部分

一、乘除运算指令

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

(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

(2)有符号数乘法指令

  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指令一般用来检测指定位上字符是否都为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之间

在这里插入图片描述

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

在这里插入图片描述

  • 循环移位指令的示例
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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云端FFF

所有博文免费阅读,求打赏鼓励~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值