该篇文章是rbpf不同码之间关系和作用的整理。
(学习该虚拟机的目的是为了搞懂solana合约的执行方式,solana使用的rbpf是在该虚拟机上进行扩展。)
汇编码(Assembly Code)是 汇编语言
的代码形式,它是低级语言的一种,介于高级语言(如 C、C++)和机器码之间。汇编码使用助记符和符号来表示机器指令,比直接使用二进制的机器码更易于人类阅读和编写,但仍然与特定的硬件架构密切相关。
字节码(Bytecode)是一种中间表示
形式(Intermediate Representation, IR),它是介于高级语言(如 Java、Python)和机器码之间的一种指令集。字节码通常由虚拟机(如 JVM、Python 解释器)解释执行,或者通过 JIT 编译器 动态编译为目标机器的机器码。
机器码(Machine Code)是 CPU 直接执行的二进制指令,它是计算机硬件能够理解和执行的最低级语言形式。机器码是编译器或汇编器将高级语言(如 C、C++)或汇编语言翻译为的最终形式
,直接在 CPU 上运行。
汇编码是语言,字节码是过渡,机器码是最终执行。
常用的x86 是一种变长指令集架构,汇编码通常以助记符表示,指令长度从 1 字节到 15 字节不等 示例 1:将立即数 42 加载到寄存器 eax
mov eax, 42
解释:
eBPF 字节码 是 eBPF 程序的中间表示形式,例如下述样式:
let prog = &[
0xb7, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
];
不同语言的字节码不同,如java虚拟机(JVM),使用自己独有字节码格式:
Compiled from "Example.java"
public class Example {
public Example();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: bipush 10 // 将常量 10 压入栈
2: istore_1 // 存储到局部变量表索引 1(a)
3: bipush 20 // 将常量 20 压入栈
5: istore_2 // 存储到局部变量表索引 2(b)
6: iload_1 // 加载局部变量表索引 1(a)
7: iload_2 // 加载局部变量表索引 2(b)
8: iadd // 整数加法
9: istore_3 // 存储结果到局部变量表索引 3(c)
10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
13: iload_3 // 加载局部变量表索引 3(c)
14: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
17: return
}
eBPF 机器码是特定于硬件架构的二进制指令,可以直接在 CPU 上运行。 不同架构的机器码完全不同。例如:
pub fn assemble(src: &str) -> Result<Vec<u8>, String> {
let parsed = (parse(src))?;
//Ok([Instruction { name: "mov", operands: [Register(0), Integer(0)] }, Instruction { name: "add", operands: [Register(1), Integer(2)] }])
let insns = (assemble_internal(&parsed))?;
let mut result: Vec<u8> = vec![];
for insn in insns {
result.extend_from_slice(&insn.to_array());
}
Ok(result)
}
汇编器就要是通过assemble方法,先对指令进行割形成列表,然后通过对不同的op码进行分类后形成对应的字节码数据。
pub fn disassemble(prog: &[u8]) {
#[cfg(feature = "std")]
{
for insn in to_insn_vec(prog) {
println!("{}", insn.desc);
}
}
反汇编则通过循环的方式切割字节码指令信息,同样通过op码进行分类转换为对应的字符串信息.
详情请查看文章:rbpf虚拟机-编译与反编译器
通过上述对不同码之间的区分,对各种格式码之间的关系认识更加清晰,同时对不同码之间的转换有了一定了解。