Jasmin汇编程序:';l2d和x27;“给予指示”;java.lang.VerifyError:。。。尝试在堆栈上拆分“长”或“双”;

Jasmin汇编程序:';l2d和x27;“给予指示”;java.lang.VerifyError:。。。尝试在堆栈上拆分“长”或“双”;,java,compiler-construction,assembly,jvm,jasmin,Java,Compiler Construction,Assembly,Jvm,Jasmin,我正在编写一个编译器,使用 我对“l2d”指令(以及相关的指令)有困难,但我认为,一旦我弄明白为什么这个指令不起作用,它们都会起作用 说明参考: 我正在编译的代码是: { double d = 10L; } 因此,本质上,我试图镜像javac在基本数值类型之间进行隐式类型转换的方式 输出Jasmin程序集代码为: .source test3.jml .class Test3 .super java/lang/Object .method public static main([Lja

我正在编写一个编译器,使用

我对“l2d”指令(以及相关的指令)有困难,但我认为,一旦我弄明白为什么这个指令不起作用,它们都会起作用

说明参考:

我正在编译的代码是:

{
    double d = 10L;
}
因此,本质上,我试图镜像javac在基本数值类型之间进行隐式类型转换的方式

输出Jasmin程序集代码为:

.source test3.jml
.class Test3
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
    .limit stack 10
    .limit locals 100
    ldc2_w 10 ;Load constant numerical value 10
    l2d ;Convert left hand side to match the type of the right
    dstore 0 ;Store top of stack in 0 (d)
.end method
重要的行是
.end method
之前的三行

“;”后面的文本这是一个评论

当我尝试运行编译后的代码时,我得到的确切错误是:

Exception in thread "main" java.lang.VerifyError:(class: Test3, method: main signature: ([java/lang/String;)V) Attempt to split long or double on the stack
Could not find the main class: Test3. Program will exit.

我认为这一定与long和double占用堆栈上的2个插槽和2个局部变量有关(已解释),但这仍然让我感到困惑。

Java虚拟机使用局部变量传递参数,因此索引为0的局部变量在代码中的类型应该是
String[]
。我对Jasmine不太熟悉,不知道在使用之前是否必须声明其他局部变量,但是您可以简单地尝试将double存储到索引1中吗?

为什么不使用真正的java编译器编译它,看看它用javap生成了什么?它应该是
dstore_0
而不是
dstore 0
,不是吗?好主意。我刚试过这个。问题是javac似乎做了很多编译时优化;它设法避免完全使用“l2d”。基本上,它意识到“=”右侧的内容将用作双精度,因此它一直将其视为双精度。即使我做了“双x=10F+12F+10;”之类的事情,它已经在编译时将整个表达式计算为“32D”。优化超出了我的项目范围。哇,很明显,它可以是。参考文献中:“dstore”在功能上等同于“dstore”,尽管它通常效率更高,字节码占用的字节也更少。”我确实打算因此更改这些,但我怀疑这是导致此问题的原因。有趣的是,尽管Jasmin的工作方式似乎不尽相同,因为我可以编写等效的代码将int转换为float,效果很好,例如float f=10;编译为:“ldc 10”然后是“i2f”然后是“fstore 0”,程序运行正常。它可能仍然相关,因为字符串数组引用仅使用一个堆栈插槽,而双堆栈插槽则需要两个。