关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »JVM 模板解释器之如何根据字节码生成汇编码?

    JVM 模板解释器之如何根据字节码生成汇编码?

    2015-08-09 00:00:00 出处:developerworks
    分享

    1、背景

    仅针对JVM的模板解释器:

    如何根据opcode和寻址模式,将bytecode生成汇编码。

    ITJS的这篇文章的示例中所使用的字节码和汇编码,请参见上篇博文:按值传递还是按引用?

    2、寻址模式

    ITJS的这篇文章不打算深入展开寻址模式的阐述,我们聚焦Intel的IA32-64架构的指令格式:

    【JVM】模板解释器–如何根据字节码生成汇编码?

    简要说明下,更多的请参考intel的手册:

    – Prefixes : 用于修饰操作码Opcode,赋予其lock、repeat等的语义.
    – REX Prefix:
    —- Specify GPRs and SSE registers.
    —- Specify 64-bit operand size.
    —- Specify extended control registers.
    –Opcode:操作码,如mov、push.
    –Mod R/M:寻址相关,具体见手册。
    –SIB:和Mod R/M结合起来指定寻址。
    –Displacement:配合Mod R/M和SIB指定寻址。
    –Immediate:立即数。

    对上面的Opcode、Mod R/W、SIB、disp、imm如果不明白,看句汇编有个概念:

    %mov %eax , %rax,-0x18(%rcx,%rbx,4)

    如果这句汇编也不太明白,那么配合下面的:

    – Base + (Index Scale) + Displacement – Using all the addressing components together allows efficient
    indexing of a two-dimensional array when the elements of the array are 2, 4, or 8 bytes in size.

    3、合法的值(64位)

    关注下这4个参数的合法取值:

    Displacement — An 8-bit, 16-bit, or 32-bit value.
    Base — The value in a 64-bit general-purpose register.
    Index — The value in a 64-bit general-purpose register.
    Scale factor — A value of 2, 4, or 8 that is multiplied by the index value.

    4、Mod R/M(32位寻址)

    我们在后文将会用到Mod R/M字节,所以将32位寻址的格式贴在这里:

    【JVM】模板解释器–如何根据字节码生成汇编码?

    上表的备注,其中第1条将在我们的示例中用到,所以这里留意下:

    The [--][--] nomenclature means a SIB follows the ModR/M byte. The disp32 nomenclature denotes a 32-bit displacement that follows the ModR/M byte (or the SIB byte if one is present) and that is
    added to the index. The disp8 nomenclature denotes an 8-bit

    5、SIB(32位寻址)

    同样,因为用到了Mod R/M字节,那么SIB字节也可能要用到:

    【JVM】模板解释器–如何根据字节码生成汇编码?

    6、示例

    6.1、准备工作

    来看个实际的例子。

    下面的代码是生成mov汇编码:

    void Assembler::movl(Address dst, Register src) {
      InstructionMark im(this);
      prefix(dst, src);
      emit_int8((unsigned char)0x89);
      emit_operand(src, dst);
    }

    prefix(dst,src)就是处理prefix和REX prefix,这里我们不关注。

    emit_int8((unsigned char) 0x89)顾名思义就是生成了一个字节,那字节的内容0×89代表什么呢?

    先不急,还有一句emit_operand(src,dst),这是一段很长的代码,我们大概看下:

    void Assembler::emit_operand(Register reg, Register base, Register index,
                     Address::ScaleFactor scale, int disp,
                     RelocationHolder const& rspec,
                     int rip_relative_correction) {
      relocInfo::relocType rtype = (relocInfo::relocType) rspec.type();
    
      // Encode the registers as needed in the fields they are used in
    
      int regenc = encode(reg) << 3;
      int indexenc = index->is_valid()   encode(index) << 3 : 0;
      int baseenc = base->is_valid()   encode(base) : 0;
    
      if (base->is_valid()) {
        if (index->is_valid()) {
          assert(scale != Address::no_scale, "inconsistent address");
          // [base + index*scale + disp]
          if (disp == 0 && rtype == relocInfo::none  &&
              base != rbp LP64_ONLY(&& base != r13)) {
            // [base + index*scale]
            // [00 reg 100][ss index base]
    
          	/**************************
    		* 关键点:关注这里
          	**************************/
    
            assert(index != rsp, "illegal addressing mode");
            emit_int8(0x04 | regenc);
            emit_int8(scale << 6 | indexenc | baseenc);
          } else if (is8bit(disp) && rtype == relocInfo::none) {
            // ...
          } else {
            // [base + index*scale + disp32]
            // [10 reg 100][ss index base] disp32
            assert(index != rsp, "illegal addressing mode");
            emit_int8(0x84 | regenc);
            emit_int8(scale << 6 | indexenc | baseenc);
            emit_data(disp, rspec, disp32_operand);
          }
        } else if (base == rsp LP64_ONLY(|| base == r12)) {
          // ... 
        } else {
    
          // ... 
        }
      } else {
        // ... 
      }
    }

    上面的代码的关注点已经标出,这里我们将其抽出,并将前文中的emit_int8((unsigned char) 0x89)结合起来:

    emit_int8((unsigned char) 0x89)
    emit_int8(0x04 | regenc);
    emit_int8(scale << 6 | indexenc | baseenc);

    最终其生成了如下的汇编代码(64位机器):

    mov    %eax,(%rcx,%rbx,1)

    好了,问题来了:

    上面这句汇编怎么得出的?

    6.2、计算过程

    我们给个下面的值:

    regenc = 0x0,scale << 6 | indexenc | baseenc = 25

    进行简单的运算就可以得到:

    emit_int8((unsigned char) 0x89) //得到0x89
    emit_int8(0x04 | regenc); //得到0x04
    emit_int8(scale << 6 | indexenc | baseenc); //得到0x19

    合起来就是三个字节:

    0x89 0x04 0x19

    1、0×89对应什么?

    【JVM】模板解释器&#8211;如何根据字节码生成汇编码?

    从上表可以看出因为JVM工作在64位下,所以需要配合REX.W来“起头”,不过在我们这个例子中,其恰好是0。

    主要看那个89/r:

    MOV r/m64,r64 //64位,将寄存器中的值给到寄存器或者内存地址中

    2、0×04代表什么?

    现在我们要用到上面的Mod R/M表和SIB表了。

    用第二个字节0×04查Mod R/M表,可知源操作数是寄存器EAX,同时可知寻址类型是[--][--]类型,含义为:

    The [--][--] nomenclature means a SIB follows the ModR/M byte.

    3、0×19代表什么?

    继续查SIB表,对应字节0×19的是:

    base = ECX
    scaled index = EBX

    4、汇编代码:

    //32位
    mov %eax,%(ecx,ebx,1)
    
    //64位
    mov %rax,%(rcx,rbx,1)

    7、结语

    ITJS的这篇文章简要探讨了:

    如何根据opcode和寻址模式,将bytecode生成汇编码。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    帝国CMS7.5编辑器上传图片取消宽高的三种方法

    帝国cms如何自动生成缩略图的实现方法

    Windows 12即将到来,将彻底改变人机交互

    帝国CMS 7.5忘记登陆账号密码怎么办?可以phpmyadmin中重置管理员密码

    帝国CMS 7.5 后台编辑器换行,修改回车键br换行为p标签

    Windows 11 版本与 Windows 10比较,新功能一览

    Windows 11激活产品密钥收集及专业版激活方法

    IT头条

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    严重缩水!NVIDIA将推中国特供RTX 5090 DD:只剩24GB显存

    00:17

    无线路由大厂 TP-Link突然大裁员:补偿N+3

    02:39

    Meta 千万美金招募AI高级人才

    00:22

    技术热点

    windows 7应用程序无法启动出现窗口提示找不到应用程序

    SQL中数据类型转换函数的使用

    MySQL使用变量的注意事项

    SQL Server 锁自定义的示例演示

    如何在Linux命令行中创建以及展示演示稿

    windows 7任务栏显示标题的方法(windows 7任务栏缩略图不显示出

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。