首页 > 其他分享 >HotSpot编译执行硬编码生成

HotSpot编译执行硬编码生成

时间:2023-07-29 23:55:10浏览次数:65  
标签:编码 x86 HotSpot emit 编译 指令 寄存器 encode int8

目录

背景

在一个技术群里,有一个哥们对着hotspot的源码问了个问题:

image

源码

看一下对应的源码

// 来源:hotspot/src/cpu/x86/vm/assembler_x86.cpp
void Assembler::notl(Register dst) {
  int encode = prefix_and_encode(dst->encoding());
  emit_int8((unsigned char)0xF7);
  emit_int8((unsigned char)(0xD0 | encode));
}

// 来源:hotspot/src/cpu/x86/vm/register_x86.hpp
// Register是RegisterImpl的指针类型
typedef RegisterImpl* Register;
class RegisterImpl: public AbstractRegisterImpl {
    ...
    // encoding函数是返回RegisterImpl实例在内存中的首地址
    // 也就是代表的寄存器的首地址
    int encoding() const {
       ... 
       return (intptr_t)this; 
    }    
    ...
}

// 来源:hotspot/src/cpu/x86/vm/assembler_x86.cpp
// 该函数输出指令前缀并返回寄存器的地址
int Assembler::prefixq_and_encode(int reg_enc) {
  if (reg_enc < 8) {
    // 寄存器地址小于8,输出指令前缀
    prefix(REX_W);
  } else {
    // 寄存器地址 >=8,输出扩展指令前缀
    prefix(REX_WB);
    // 减8是因为只有8个通用寄存器
    reg_enc -= 8;
  }
  // 返回寄存器的首地址
  return reg_enc;
}

// 来源:hotspot/src/cpu/x86/vm/assembler_x86.cpp
// 输出8个位
void emit_int8(int8_t  x) { 
    code_section()->emit_int8(x); 
}
// 来源: hotspot/src/share/vm/asm/codeBuffer.hpp
// 汇编代码缓冲区,写入8bit
 void emit_int8 (int8_t  x)  { 
     // end()位子写入x
     *((int8_t*) end()) = x; 
     // end位置往后+8
     set_end(end() + sizeof(int8_t)); 
 }

从源码上看,理解到了HotSpot在编译执行时,生成汇编代码的实现动作。但是为什么not寄存器指令要输出 emit_int8((unsigned char)0xF7);emit_int8((unsigned char)(0xD0 | encode));

指令

看一下X86架构一条指令的结构:

image

  • Instruction Prefixes:指令前缀,非必须
  • Opcode:指令,必须
  • ModR/M:扩展指令,非必须
  • SIB:扩展指令增强,非必须
  • Displacement:偏移量,非必须
  • Immediate:立即数,非必须

当前not指令只用到了Opcode和ModR/M两个结构:

image

那输出的 0xF7,0D0 | encode到底是什么意思呢?

解析硬编码

先不考虑 |(或)运算

0xF7D0 = 0xF7 11 010 000

通过《Intel 开发手册》查表:

image

F7和010的组合代表 not 指令

image

11 和 000 ~ 111的组合代表具体的寄存器,或运算就是决定具体的寄存器

总结

更深入理解JVM(HotSpot)编译执行落地过程

标签:编码,x86,HotSpot,emit,编译,指令,寄存器,encode,int8
From: https://www.cnblogs.com/ylc0x01/p/17590839.html

相关文章

  • EC11编码器消抖
    前言之前在网上看到一篇文章优雅的对旋转编码器消抖(EC11,正交)-知乎(zhihu.com)感觉大佬用的方法挺不错的,这里在STM32上使用一下看下效果。消抖原理消抖的核心思路:A脚设置为上升下降沿均会进中断,下降上升一个变换周期,判断这个周期的A脚,B脚的始末状态,来判断正反转一次。......
  • Vue3.3 编译宏
    Vue3.3新增了一些语法糖和宏,包括泛型组件、defineSlots、defineEmits、defineOptionsdefineProps父子组件传参<template><div><Childname="xiaoman"></Child></div></template><scriptlang='ts'setup>importChildf......
  • html实体编码
    1、介绍html虽然不是程序语言,但也存在某些预留字符用于结构描述,以及某些无法键盘输入的字符。因此也需要类似\的转义。在html中,称为实体编码,与\转义有所不同。2、html实体编码html实体编码有三种格式。这三种作用是相同的。实体名称&nbsp;十进制实体编号&#160;八进制实......
  • url编码
    1、介绍(1)编码方案url中存在某些敏感字符作为其结构描述符,如果要表达敏感字符作为普通文本,需要进行转码,即url编码。url编码是将字符转为utf-8,然后对每个字节前加%字符。一般,会对url结构描述符、ascii无法直接表达的字符、以及超出ascii编码的字符进行转码,而其他是否转码均可。......
  • 编码基础
    1、比特比特是数字电路的产物,用于描述最基础的电路单元的状态。另一方面,比特作为最小单元用于对抽象的指令或者数据进行描述。也就是说,比特是计算机和计算机网络中最小的信息量单位。人为的规定并遵循其进行电路设计:一个比特有且只有两个状态,即0和1。2、字节字节是计算机中常......
  • v831-c-编译环境部署篇
    学了一遍又学回来了,整理整理v831的环境吧头文件这些头文件上面部分是在python里面在编译成可执行文件之前会创造出来的,不用理他下面则是components里面的,需要在.vscode里面设置一下路径这样基本上就可以了,其他的我们不再vscode里面一键操作,就不设置了工具链路径工具链的路......
  • 反编译工具 Fernflower
    反编译.class文件工具Fernflower首先需要下载依赖包 http://the.bytecode.club/fernflower.jar下载后,切换到文件当前目录,直接使用命令 java-jarfernflower.jar目标文件目标路径 进行反编译即可反编译后的文件会生成到指定目录......
  • unicode编码
    1、unicode编码unicode统一码,万国码,单一码,是计算机科学领域的一项业界标准。是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。官网:https://home.unicode.org/1.1版本unicode......
  • ascii编码
    1、介绍ASCII(AmericanStandardCodeforInformationInterchange):美国信息交换标准代码是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准ISO/IEC646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更......
  • 01_llvm编译及创建一个module试用llvm
    LLVM源码编译准备好匹配的环境后,我的环境如下:$cat/proc/versionLinuxversion5.4.0-150-generic(buildd@bos03-amd64-012)(gccversion7.5.0(Ubuntu7.5.0-3ubuntu1~18.04))#167~18.04.1-Ubuntu如果环境较老,可checkout到比较老的分支再编,不然容易出现各种软件版本不......