以字节码格式存储值
Storing values in bytecode format
我已经在 Java 中创建了一个原型 VM(因为它是我最熟悉的语言)并且我正在尝试以字节码格式存储指令。我想知道如何在字节码中存储值,因为 bytes 只能是 0 到 255。
举个例子:
push 4752
Push 的操作码值为 0。
但是我怎么能存储 4752 呢?它不适合单个字节。
我可以用 4 个字节存储值,因此允许它们是 32 位整数,但是我必须决定是加载一个操作码(1 个字节)还是一个值(4 个字节)。目前我将程序作为整数数组传递,VM 循环遍历该数组并执行操作码。如果操作码需要一个值,它会从数组中获取它,然后增加程序计数器以跳过该值,这样它就不会被执行。
我试图弄清楚像 JVM 这样的虚拟机是如何做到这一点的,但我无法找到答案。
JVM 有几个选项允许对预期更频繁的案例进行较小的编码,因此平均而言,方法和 类 的编码较小。具体看下面的说明
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5(或 se8,但 IIRC none 的基本 arithmetic/computation 指令在 7 和 8 之间发生了变化,只有一个或两个 invoke 指令):
- iconst_ 是推送特定值 "m1" (-1) 到 5
的单独操作码
- bipush 从指令流中推送下一个字节
- sipush 从指令流中推送接下来的两个字节
- ldc 或 ldc_w 从常量池中压入一个四字节的值,由 [=20=指令流中的]index
您的示例值 4752 适合两个字节,将使用 sipush。
为了扩展您的问题,JVM 中的 long
(64 位或 8 字节)值主要是通过推送 int
然后扩大它,或者通过推送来自 long
变量或字段(或方法 return)。有一条指令 ldc2_w 从常量池中推送一个 2 单元格(8 字节)的值,还有两条 special-for-frequent 指令 lconst_0 和 lconst_1 对于 0 和 1.
我已经在 Java 中创建了一个原型 VM(因为它是我最熟悉的语言)并且我正在尝试以字节码格式存储指令。我想知道如何在字节码中存储值,因为 bytes 只能是 0 到 255。
举个例子:
push 4752
Push 的操作码值为 0。 但是我怎么能存储 4752 呢?它不适合单个字节。 我可以用 4 个字节存储值,因此允许它们是 32 位整数,但是我必须决定是加载一个操作码(1 个字节)还是一个值(4 个字节)。目前我将程序作为整数数组传递,VM 循环遍历该数组并执行操作码。如果操作码需要一个值,它会从数组中获取它,然后增加程序计数器以跳过该值,这样它就不会被执行。
我试图弄清楚像 JVM 这样的虚拟机是如何做到这一点的,但我无法找到答案。
JVM 有几个选项允许对预期更频繁的案例进行较小的编码,因此平均而言,方法和 类 的编码较小。具体看下面的说明 https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5(或 se8,但 IIRC none 的基本 arithmetic/computation 指令在 7 和 8 之间发生了变化,只有一个或两个 invoke 指令):
- iconst_ 是推送特定值 "m1" (-1) 到 5 的单独操作码
- bipush 从指令流中推送下一个字节
- sipush 从指令流中推送接下来的两个字节
- ldc 或 ldc_w 从常量池中压入一个四字节的值,由 [=20=指令流中的]index
您的示例值 4752 适合两个字节,将使用 sipush。
为了扩展您的问题,JVM 中的 long
(64 位或 8 字节)值主要是通过推送 int
然后扩大它,或者通过推送来自 long
变量或字段(或方法 return)。有一条指令 ldc2_w 从常量池中推送一个 2 单元格(8 字节)的值,还有两条 special-for-frequent 指令 lconst_0 和 lconst_1 对于 0 和 1.