当前位置: 首页 > news >正文

特殊的算术操作指令

 我们先来看看这些指令的大致介绍,如果各位看过上一章的话,会发现这里的指令有的会有些眼熟,但是它们的作用却截然不同。以下是书中的一张概图。

  第一个指令有些眼熟吧,它就是我们上一章当中的imul乘法指令的双字形式。不过可以看出,这里的imull指令已经完全变了味道,它将结果存入两个寄存器。接下来,我们来仔细看看这些指令。

 

imull、mull指令

  这两个指令一看就是双胞胎,它们一个负责有符号全64位乘法,一个负责无符号全64位乘法。细心的猿友会发现,imull这个指令好像是负责乘法的指令,而且在之前的乘法并没有区分有符号和无符号,现在怎么又成双胞胎指令了。

  我们上一章当中出现的指令是imul指令,当它操作双字的时候,也就是imull指令。不过不同的是,它的一般形式是imull S D,这里有两个操作数,它将计算S和D的乘积并截断为双字,然后存储在D当中。由于在截断时,无符号以及有符号的二进制序列是一样的,因此此处的乘法指令并不区分有符号和无符号。

  本次我们讨论的imull指令,则与上面的普通乘法指令稍有不同,它只有一个操作数,也就是说,它的一般形式为imull S,这点在书中的表格中也能看出来,而另外一个操作数默认为%eax寄存器。最终的结果,会将高32位存入%edx寄存器,而低32位存入%eax寄存器。

  试想一下,如果我们只取%eax寄存器当中的32位结果,那其实这里计算的结果就是S*%eax,此时imull S的作用就与imull S D是一样的,只是目的操作数被固定为%eax罢了。

  接下来我们看一个简单的示例,我们去看下指令imull $0x3的结果,我们假设此时%eax寄存器的值为0x82345600。也就是我们需要计算0x3*0x82345600的值,这里LZ直接给出两者相乘的16进制表示,各位有兴趣的可以私下乘一下,为0xFFFF FFFE 869D 0200。这个结果为64位的,因此我们寄存器的前后状态如下所示。

  可以看到,%eax保存着低32位的结果,单说这32位的话,它的有符号数值为-2036530688,正是我们直接计算0x3*0x82345600的32位截断后的有符号值,显然这个结果溢出了。如果组合上高32位,则结果为-6331497984,将它加上或者取模4294967296(2的32次方)将得到我们32位的结果。这里的有符号乘法采取的是先符号扩展被乘数,然后两者相乘,将结果再截断为64位所得。

  对于mull的单操作数指令来讲,就比较简单了,它采用的是无符号乘法,因此就和我们平时的十进制乘法运算类似,只是同样的,它也会将结果的高32位存入%edx,将低32位存入%eax。

cltd指令

  这个指令相对来说就非常简单了,它就是简单的将%eax寄存器的值符号扩展32位到%edx寄存器,也就是说,如果%eax寄存器的二进制序列的最高位为0,则cltd指令将把%edx置为32个0,相反,如果%eax寄存器的二进制序列最高位为1,则cltd指令将会自从填充%edx寄存器为32个1。

 

idivl、divl指令

  这两个指令与前面的imull以及mull类似,它也将计算结果存放在两个寄存器当中,其中余数存放在%edx寄存器,商存放在%eax寄存器。如果各位理解了前面的imull以及mull,那么这里idivl和divl理解起来会非常简单。

  这里LZ举一个简单的例子,考虑指令idivl $0x3的结果,我们假设此时%eax寄存器的值为0x82345600。也就是我们需要计算0x82345600/0x3的值,这里LZ直接给出两者相除的16进制表示,各位有兴趣的也可以私下除一下,商为0xD6117200,余数为0x0。因此我们寄存器的前后状态如下所示。

  可以看到,在idivl这个指令执行的过程中,其实对被除数进行了符号扩展,类似于cltd指令,或者有时也会将%eax移动到%edx,然后对%edx进行算术右移31位的运算。这两种方式的结果是一样的,都是将%eax符号扩展32位并存储在%edx当中。

 

转自:


作者:zuoxiaolong(左潇龙)

出处:博客园左潇龙的技术博客--http://www.cnblogs.com/zuoxiaolong

转载于:https://www.cnblogs.com/zzdbullet/p/9625566.html

相关文章:

  • jchdl - RTL Data Types
  • Python基础之for循环
  • 刚在虚拟机上装的Linux系统,ifconfig后IP地址怎么成了127.0.0.1了
  • 教你利用Python把图片转字符画!代码哆啦A梦你见过嘛?
  • MongoDB 有关实体映射具体应用及对查询的影响
  • Zabbix篇二:Linux批量安装客户端Zabbix-agent
  • 重新思考数据输入
  • EasyUI的Vue版本
  • mi家前端面经
  • cpp学习(一)环境搭建
  • Facebook 开发的 HHVM 引擎宣布停止支持 PHP
  • 面向对象:classmethod、staticmethod、property
  • 面试宝典系列-nginx的缓冲和缓存
  • GitHub:我们为什么会弃用jQuery?
  • PostgrepSQL(大象)的使用
  • Codepen 每日精选(2018-3-25)
  • go append函数以及写入
  • HashMap剖析之内部结构
  • Java 最常见的 200+ 面试题:面试必备
  • SpiderData 2019年2月25日 DApp数据排行榜
  • SSH 免密登录
  • Terraform入门 - 3. 变更基础设施
  • vue2.0项目引入element-ui
  • 彻底搞懂浏览器Event-loop
  • 大快搜索数据爬虫技术实例安装教学篇
  • 大型网站性能监测、分析与优化常见问题QA
  • 精彩代码 vue.js
  • 老板让我十分钟上手nx-admin
  • 配置 PM2 实现代码自动发布
  • 通过git安装npm私有模块
  • 学习HTTP相关知识笔记
  • 以太坊客户端Geth命令参数详解
  • 在weex里面使用chart图表
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • puppet连载22:define用法
  • 阿里云服务器如何修改远程端口?
  • #控制台大学课堂点名问题_课堂随机点名
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (转)原始图像数据和PDF中的图像数据
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .NET MVC第五章、模型绑定获取表单数据
  • .NET NPOI导出Excel详解
  • .Net 高效开发之不可错过的实用工具
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • .Net调用Java编写的WebServices返回值为Null的解决方法(SoapUI工具测试有返回值)
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • @Builder用法
  • [20190401]关于semtimedop函数调用.txt
  • [Android]如何调试Native memory crash issue
  • [Angularjs]asp.net mvc+angularjs+web api单页应用之CRUD操作