文章目录
- 一、概述
- 二、eBPF 的指令格式
- 三、Opcode 具体字段解释
- 1. 操作码(OP,7~4位)4位
- 2. 访问模式(MODE,3~2位)2位
- 3. 数据大小(SIZE,1~0位) 2位
- 三、具体使用
- 四、总结
Welcome to Code Block's blog本篇文章主要介绍了
[rbpf虚拟机-opcode码]
❤博主广交技术好友,喜欢我的文章的可以关注一下❤
一、概述
该篇文章是rbpf虚拟机opcode码作用和使用的整理。
(学习该虚拟机的目的是为了搞懂solana合约的执行方式,solana使用的rbpf是在该虚拟机上进行扩展。)
经过验证器后在rbpf虚拟机需要知道每条指令是用来做什么的,就需要用到opcode码,opcode码中由8种操作码、5种访问模式、4种数据大小进行组合获得,其结构如下图:
7 6 5 4 | 3 2 | 1 0
+---------------+--------+--------+
| 操作码 | 访问模式 | 大小 |
+---------------+--------+--------+
二、eBPF 的指令格式
完整的 eBPF 指令通常是 8 字节(64 位),其中 opcode 仅占 低 8 位,其余部分包含寄存器编号、立即数等。
31 24 23 16 15 8 7 0
+--------+--------+--------+--------+
| dst | src | offset | opcode |
+--------+--------+--------+--------+
| immediate / address |
+----------------------------------------+
字段说明:
字段 | 位数 | 说明 |
---|---|---|
opcode | 8-bit | 操作码,包括 OP、MODE 和 SIZE |
dst | 4-bit | 目标寄存器编号 |
src | 4-bit | 源寄存器编号(用于二元运算) |
offset | 16-bit | 偏移量(用于内存访问或跳转) |
immediate | 32-bit | 立即数(用于算术或跳转指令) |
三、Opcode 具体字段解释
1. 操作码(OP,7~4位)4位
Opcode 值 | 名称 | 说明 |
---|---|---|
0x00 | BPF_LD | 立即数/内存加载指令 |
0x40 | BPF_LDX | 从内存加载到寄存器 |
0x60 | BPF_ST | 存储指令(寄存器 → 内存) |
0x61 | BPF_STX | 存储指令(寄存器 → 内存,带索引) |
0x80 | BPF_ALU | 算术运算(立即数模式) |
0xc0 | BPF_ALU64 | 64 位算术运算 |
0xa0 | BPF_JMP | 跳转指令 |
0xe0 | BPF_JMP32 | 32 位跳转指令 |
2. 访问模式(MODE,3~2位)2位
Mode 值 | 名称 | 说明 |
---|---|---|
0x00 | BPF_IMM | 立即数模式(直接使用值) |
0x10 | BPF_ABS | 绝对地址模式(用于 BPF_LD ) |
0x20 | BPF_IND | 间接地址模式(用于 BPF_LD ) |
0x60 | BPF_MEM | 内存模式(从内存读取/写入) |
0x70 | BPF_LEN | 报文长度(仅在 BPF_LD 使用) |
3. 数据大小(SIZE,1~0位) 2位
Size 值 | 名称 | 说明 |
---|---|---|
0x00 | BPF_W | 4 字节(32 位) |
0x08 | BPF_H | 2 字节(16 位) |
0x10 | BPF_B | 1 字节(8 位) |
0x18 | BPF_DW | 8 字节(64 位) |
三、具体使用
opcode码有很多种,如果直接使用如:0x71
表示从内存加载 1 字节到寄存器
,在定义时如果使用:
LD_B_REG = 0x71
这读起来有点费力,不利于维护操作。为了解决这一问题,可以直接将上述的操作码、访问模式、数据大小进行预先定义,然后使用以下方式进行定义:
LD_B_REG = BPF_LDX | BPF_MEM | BPF_B
BPF_LDX表示从内存加载到寄存器,BPF_MEM表示内存模式,BPF_B表示1个字节。这时我们就可以清楚的知晓LD_B_REG为从内存加载 1 字节到寄存器
。这样,哪怕不知道是什么值,也可以通过按位或计算得到
opcode(操作码).
LD_B_REG = BPF_LDX | BPF_MEM | BPF_B= 0x61 | 0x00 | 0x10= 0b0110 0001 | 0b0000 0000 | 0b0001 0000------------------------------------------= 0b0111 0001 // 结果 = 0x71(十六进制)
四、总结
通过上述对opcode码结构进行解读,对opcode码有了更深刻的理解,同时这种结构组合按位或处理可以产生很多组合结果,该方法可以很好的运用到日常的其它语言项目中。
代码来源:rbpf虚拟机
鸣谢: qmonnet 提供的开源代码.
当然,我也会将带有中文注释和自己理解的一些代码上传的我的github页面,感兴趣的朋友可以进行clone查看.
我的GitHub:forked
感谢您的点赞、关注、收藏!