专栏首页IT可乐深入理解计算机系统(3.5)------特殊的算术操作指令

深入理解计算机系统(3.5)------特殊的算术操作指令

  在上一篇博客 算术和逻辑操作 我们介绍了如下图几种常用的算术逻辑指令,但是大家发现没,这几种指令如果在 IA32 上只能操作32位寄存器,比如我用乘法指令IMUL得出的结果超过了32位,那就会产生结果溢出,那应该怎么办呢?

1、特殊的算术操作指令指令

  如上图,上面的几个指令支持有符号和无符号的全64位乘积以及整数除法,但是需要注意的是,存储结果的寄存器固定死了,是一对寄存器%edx(高32位)和%eax(低32位)组成的 64 位的四字。

2、imull 和 mull 指令

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

  但是对于本章的 imull 指令,它和前面的所表示的乘法指令有所不同,这里只有一个操作数,如上图,它的指令形式是 imull S。但是实际上它还有一个默认的操作数——寄存器%eax,这两者相乘,最终的结果是将高32位存入%edx 寄存器,低 32 位存入%eax 寄存器。

  如果我们只取低 32 位的结果,那么这里指令的意思和上篇博客所讲的乘法指令意思是一样的了,imull S D,只不过这里的D是寄存器 %eax。

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

  本实例引用:http://www.cnblogs.com/zuoxiaolong/p/computer17.html

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

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

  所以虽然 imull 可以用于两种不同的乘法操作,但是汇编器能够通过计算操作数的数据,分辨出想用哪条指令。

3、cltd 指令

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

4、idivl、divl指令

  这两个指令分别是有符号除法和无符号除法指令,有符号除法指令 idivl 将寄存器 %edx(高32位)和 %eax(低32位)中的64位数作为被除数,而除数作为指令的操作数给出。指令将商存储在寄存器 %eax 中,将余数存储在寄存器 %edx 中。

  比如指令idivl $0x3的结果,我们假设此时%eax寄存器的值为0x82345600。也就是我们需要计算0x82345600/0x3的值,这里直接给出两者相除的16进制表示,商为0xD6117200,余数为0x0。因此我们寄存器的前后状态如下所示。

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 深入理解计算机系统(3.4)------算术和逻辑操作

      上一篇博客  我们介绍了几种数据传送指令,包括MOV,MOVS,MOVZ,PUSH和POP等,理解起来也不算难。本篇博客我们来接着看汇编语言的算术与逻辑运算...

    IT可乐
  • 深入理解计算机系统(3.3)------操作数指示符和数据传送指令

      在上一篇博客 程序编码以及数据格式 中我们给出了一个简单的C程序,然后编译成了汇编代码。大家看不懂没关系,后面的博客我们将逐渐揭开一些汇编指令的神秘面纱。本...

    IT可乐
  • 深入理解计算机系统(3.6)------汇编的流程控制

      前面我们所讲的所有指令,代码执行顺序都是一条接着一条顺序的执行。但是实际上在编码过程中,会有某些结构,比如条件语句(if-else),循环语句(for,do...

    IT可乐
  • 深入理解计算机系统(3.4)------算术和逻辑操作

      上一篇博客  我们介绍了几种数据传送指令,包括MOV,MOVS,MOVZ,PUSH和POP等,理解起来也不算难。本篇博客我们来接着看汇编语言的算术与逻辑运算...

    IT可乐
  • Leetcode#832. Flipping an Image(翻转图像)

    水平翻转图片就是将图片的每一行都进行翻转,即逆序。例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]。

    武培轩
  • Java容器(List、Set、Map)知识点快速复习手册

    容器主要包括 Collection 和 Map 两种,Collection 又包含了 List、Set 以及 Queue。

    后端技术漫谈
  • HashMap 和 currentHashMap 终于总结清楚了!

    通过给定值进行查找,需要遍历数组,逐一比对给定关键字和数组元素,时间复杂度为O(n),当然,对于有序数组,则可采用二分查找,插值查找,斐波那契查找等方式,可将查...

    Java技术栈
  • Java之手写HashMap(上)

    前面手写了MyArrayList以及MyLinkedList了,现在写的hashmap主要小编只采取数组加链表的方式来写了,那么现在就废话不多说了,还是和以前一...

    用户5224393
  • Key-Value Memory Network

    Deep Memory Network 深度记忆网络 Deep Memory Network在Aspect Based Sentiment方向上的应用(opt...

    Steve Wang
  • P3375 【模板】KMP字符串匹配(全程注释,简单易懂)

    题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。 为了减少骗分的情况,接下来还要输出子串的前缀数组next。如果...

    attack

扫码关注云+社区

领取腾讯云代金券