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

openjdk底层汇编指令调用(三)——编码

有了寄存器的编号实现,现在讨论如何实现指令编码。还是以AArch64指令为例进行说明。假设指令为add x0,x1,x2,根据指令手册可知

在这里插入图片描述
其机器码为

#二进制
10001011000 00010 000000 00001 00000#十六进制
0x8B020020
#小端编码需要反转
0x2000028B

回到源码文件assembler_aarch64.hpp。该文件中定义了汇编器类(Assembler)。在英文中(雅思7分,口语8分,炫耀一下),汇编(assemble)的原意是生产线上组装零件的意思。根据计算机的知识,汇编器(assembler)的作用就是根据手册组装指令中的各个部分。根据手册中该指令描述可知,至少有几处是需要填充值。如果要形成完整的指令则需将这些部分组装(assemble)起来。

在源码中如何实现上述的add指令呢?其实现原理是将手册中各部分用编码替代,然后进行拼装。assembler_aarch64.hpp文件的如下代码实现了add x0,x1,x2指令的编码

#define INSN(NAME)                                      \void NAME(Register Rd, Register Rn, Register Rm) {    \if (Rd == sp || Rn == sp)                           \NAME(Rd, Rn, Rm, ext::uxtx);                      \else                                                \NAME(Rd, Rn, Rm, LSL);                            \}...INSN(add);

上述INST(add)宏展开之后如下

void add(Register Rd, Register Rn, Register Rm) { if (Rd == sp || Rn == sp) add(Rd, Rn, Rm, ext::uxtx); else add(Rd, Rn, Rm, LSL); 
}

很明显,如要实现add x0,x1,x2的编码,需调用的add(Rd,Rn,Rm,LSL)函数,其具体实现如下

  // Add/subtract (shifted register)
#define INSN(NAME, size, op)                            \void NAME(Register Rd, Register Rn, Register Rm,      \enum shift_kind kind, unsigned shift = 0) { \starti;                                             \f(0, 21);                                           \assert_cond(kind != ROR);                           \zrf(Rd, 0), zrf(Rn, 5), zrf(Rm, 16);                \op_shifted_reg(0b01011, kind, shift, size, op);     \}INSN(add, 1, 0b000);

宏展开代码为

void add(Register Rd, Register Rn, Register Rm, enum shift_kind kind, unsigned shift = 0) { Instruction_aarch64 do_not_use(this); set_current(&do_not_use); f(0, 21); ; zrf(Rd, 0), zrf(Rn, 5), zrf(Rm, 16); op_shifted_reg(0b01011, kind, shift, 1, 0b000); 
}

这里首先要明白f函数的作用:

/*
* 将val的值放入lsb(低位)至msb(高位)区间
*/
void f(unsigned val, int msb, int lsb) {current->f(val, msb, lsb);
}

因此f(0,21)表示在21位上设置为0,符合手册要求的格式
在这里插入图片描述

其他函数如zrfop_shifted_reg均是在内部调用f函数以实现在编码各位置上的赋值,这里对zrf函数的实现不再赘述,简单分析一下op_shifted_reg函数
在这里插入图片描述
因此op_shifted_reg将22至31位上按照手册要求赋值。

通过add(Register Rd, Register Rn, Register Rm, enum shift_kind kind, unsigned shift = 0) 的调用可完成add x0,x1,x2汇编指令的编码。其中Rmr1替换,Rnr2替换,Rdr0替换。关于寄存器定义的内容参见寄存器定义。

指令编码完成后,如果需要执行该指令,则需将其放入内存的指令区域,然后让程序计数器(PC)指向该指令地址,CPU读取该指令执行即可。

相关文章:

  • CSS可以继承的样式汇总
  • 【fastadmin开发实战】在前端页面中使用bootstraptable以及表格中实现文件上传
  • 使用全局状态管理(Vuex)实现数据共享​
  • “新五强”争锋,基础大模型玩家再洗牌
  • RTSP有两套格式吗?
  • 从数据中台到数据飞轮:实现数据驱动的升级之路
  • 【C++进阶篇】二叉搜索树的实现(赋源码)
  • 量化感知训练与 PyTorch 的哪些事
  • rocketMq实例
  • 高防服务器部署实战:从IP隐匿到协议混淆
  • 可视化+智能补全:用Database Tool重塑数据库工作流
  • 星云智控自定义物联网实时监控模板-为何成为痛点?物联网设备的多样化-优雅草卓伊凡
  • 视频编辑软件无限音频、视频、图文轨
  • 【HarmonyOs鸿蒙】七种传参方式
  • Python 基础语法与数据类型(八) - 函数参数:位置参数、关键字参数、默认参数、可变参数 (*args, **kwargs)
  • 【车辆管理软件】佳易王车辆运行信息管理系统:物流车队车辆管理软件!车辆运行日报报表打印软件程序实操教程 #操作简单 #记录车辆数据软件
  • Linux 下载python3.9
  • 分别在windows和linux上使用curl,有啥区别?
  • 精准预测蛋白质稳定性的强大工具
  • mpegts.js 播放flv视频报错:PIPELINE_ERROR_DECODE: video decode error!
  • 国务院办公厅印发《国务院2025年度立法工作计划》
  • 陕西河南山西等地将现“干热风”灾害,小麦产区如何防范?
  • 颜福庆与顾临的争论:1930年代在中国维持一家医学院要花多少钱
  • 重庆发布经济犯罪案件接报警电子地图,企业可查询导航属地经侦服务点
  • 国务院关税税则委:调整对原产于美国的进口商品加征关税措施
  • 北京今日白天超30℃晚间下冰雹,市民称“没见过这么大颗的”