Chinaunix首页 | 论坛 | 博客
  • 博客访问: 458389
  • 博文数量: 153
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1575
  • 用 户 组: 普通用户
  • 注册时间: 2016-12-20 17:02
文章分类

全部博文(153)

文章存档

2017年(111)

2016年(42)

我的朋友

分类: Java

2017-01-06 17:02:12

概述

之所以会写这个,主要是因为最近做的一个项目碰到了一个移位的问题,因为位移操作溢出导致结果不准确,本来可以点到为止,问题也能很快解决,但是不痛不痒的感觉着实让人不爽,于是深扒了下个中细节,直到看到Intel的指令规约才算释然,希望这篇文章能引起大家共鸣。

本文或许看起来会比较枯燥,不过其实认真看挺有意思的,如果实在看不下去,告诉你一个极简路径,先看下下面的Demo,然后直接跳到后面的小结,如果懂了,别忘记顺便点个赞,请叫我雷锋,哈哈。

Demo

还是从一个简单的例子说起

public class ShiftTest { public static void main(String args[]) {
        System.out.println(doShiftL(35));
    } public static long doShiftL(int shift) { return 4 << shift;
    }
} 

大家可以尝试做几个改变,看看结果怎样

  • 4 << shift改成4L << shift
  • 将35改成291,PS:提示一下291=35+256*1

如果上面的各种结果你都能解释,那说明你对位移操作还是有一定了解的,不过本文主要从JVM到Intel X86_64指令角度来分析这个问题,或许也值得一看

JVM里4和4L的区别

要知道区别,我们看doShiftL方法通过javac编译出来的指令有什么不一样

4 << shift的字节码

 0: iconst_4 1: iload_0 2: ishl 

4L << shift的字节码

 0: ldc2_w        #34                 // long 4l 3: iload_0 4: lshl 

针对4和4L的区别,我们看到了两条不同的指令,分别是iconst_4和ldc2_w,其实如果我们将4改成其他的值,可能会有不一样的指令出现

  • -1<= x <=5: iconst_x
  • -128<= x <-1 || 5< x <=127:bipush
  • -32768 <= x < -128 || 127 < x <= 32767:sipush
  • -32768 > x || x > 32767:ldc

不过这些都不是我们今天的重点,不想细说了,就以iconst_4为例来简单介绍下

iconst_4

先看iconst_4的大概汇编指令如下

 0x00007fcb529b0b00: push %rax 0x00007fcb529b0b01: jmpq 0x00007fcb529b0b30 0x00007fcb529b0b06: sub $0x8,%rsp 0x00007fcb529b0b0a: movss %xmm0,(%rsp) 0x00007fcb529b0b0f: jmpq 0x00007fcb529b0b30 0x00007fcb529b0b14: sub $0x10,%rsp 0x00007fcb529b0b18: movsd %xmm0,(%rsp) 0x00007fcb529b0b1d: jmpq 0x00007fcb529b0b30 0x00007fcb529b0b22: sub $0x10,%rsp 0x00007fcb529b0b26: mov %rax,(%rsp) 0x00007fcb529b0b2a: jmpq 0x00007fcb529b0b30 0x00007fcb529b0b2f: push %rax 0x00007fcb529b0b30: mov $0x4,%eax 0x00007fcb529b0b35: movzbl 0x1(%r13),%ebx 0x00007fcb529b0b3a: inc %r13 0x00007fcb529b0b3d: mov $0x7fcb63dd5760,%r10 0x00007fcb529b0b47: jmpq   *(%r10,%rbx,8) 

重点看0x00007fcb529b0b30这条就是将0x4移到EAX寄存器里,这是一个32位的寄存器,需要注意的是这里并没有直接将4 push到操作数栈上,而是在下一条指令(也就是iload_0)执行的时候才预先push到栈上,后面看iload_0的汇编代码可知


阅读全文请点击:
阅读(1491) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~