Java中的内联ASM

时间:2015-04-06 23:29:15

标签: java c assembly

自从我开始在Java中嵌入asm用于Intel x86 64位处理器并无缝运行和编译这些方法(后来可能将这些调用模拟为后退)时,我想知道是否存在x86编译器的Java实现已经存在。我也想要支持那些高级指令。

目标是最终得到类似的东西:

public int myJavaMethod(long value) {
    doSomeJavaStuff...

    int result = 0;
    asm("             push eax",
        "             mov eax, value",
        "             cmp eax, 0",
        "             jne notEqual",
        "             mov result, 1",
        "             jmp done",
        "notEqual:    mov result, 0",
        "done:        pop eax");

    doSomeMoreJavaStuff();
    return result;
}

我有什么:

  • 英特尔的OPCodes和架构手册(VOL2)
  • 我正式使用JNA编译并运行asm(" nop")程序部分

当前的挑战:

由于任务的性质,我将尝试访问底层JavaVM堆栈帧 - 这是可能的(记住你得到esp堆栈指针和基本指针ebp,即使是ret op将放置在的地址) eip指针)但是将解决方案与某个java VM +构建目标结合起来,我没有遇到任何问题,因为可以创建各种目标适配器并在JavaVM实现中进行探索将会很有趣和有趣。

上述基于字符串的解决方案的问题在于参数和结果的处理。可能有必要提供参数映射,如asm(params(结果,值,等等),"操作码"),并将输出变量直接放在正确的内存插槽或JIT用于填充的寄存器中params中的变量调用或执行类似result = asmResult(result)的操作,以从asm调用的数据部分读取实际更改的值,并将其放在正确的值中。

通过对这些信息使用Unsafe,甚至可以访问Object和Class变量并导航这些值,获取asm代码中使用的所有引用的地址和类型。因此,在不干扰Java的情况下使用asm(" mov eax,super.field")是可能的 - 除非JIT再次对寄存器缓存进行一些有趣的优化,但可能不太可能,因为asm(...)是一个某些调用和缓存对象变量内容可能违反有关对象的并发条件。但对于Oracle的JVM开发人员来说,这又是一个问题。

因此,如果您有任何有关现有Java代码或C代码的信息可以帮助我完成这样的事情,那么欢迎您。

最好的帮助是x86编译器的Java实现,它已经有了在一系列字节(操作码)中转换某些asm结构的方法,所以我可能只需从上面的调用中创建一个真正的ASM方法以及通过检查方法字节代码以及Unsafe和任何信息来源收集的信息。

最后,我想在我的Java代码中编写汇编程序而不需要详细编写c / ASM,为不同的操作系统和平台加载库。没有意义。一旦这个工作,人们可以很容易地生成" C"函数按需调用,甚至可能绕过JNA摆脱另一个依赖。

因此,如果您了解代码和项目或有其他信息,欢迎您。

[更新]

这个问题不针对JNI / JNA。目标是绕过使用外来编译器并加载库。这个想法只是直接从Java内部编译到内存中,并通过使用指向它的指针以及一些用于参数和值处理的附加数据来启动方法。

只要想想这个工作流编写C / ASM,使用gcc编译,loadLibrary,通过JNA调用方法将工作流编译(使用Java)放入内存,通过JNA调用方法。我已经可以做到这一点我只想使用更多的操作码而不创建我自己的编译器前端。这不是关于这是否可能,而是关于如何懒惰地做。

但是,一旦我展示了基本的可行性,我猜人们会加入更多目标平台(我只针对Linux和i5 + Intel Xeon v3处理器)。

[更新2]

目前,我正在调查NASM编译器,因为它被认为是一个使用Intel表示法的优秀且积极开发的编译器。我已经向开发人员询问了如何实现透明,简单和快速(例如无磁盘访问)集成。如果这有效,那么使用流行的编译器为C创建类似的解决方案也是可能的。

这个想法是在eclipse中编辑Java源代码,运行程序完成。使用不同语言编写这些片段以及调用和所有其他乐趣应该是完全透明的。

1 个答案:

答案 0 :(得分:2)

我不知道你怎么能真正做到这一点。我认为你在这里遗漏了很多东西,首先想到的主要事情是:

  • Java编译为字节码,这与英特尔的组合无关。 JVM是基于堆栈的机器,而Intel CPU(主要)是基于寄存器的。
  • 当大多数内联汇编用于此目的时,Java无法直接访问硬件或系统调用,因为它在VM上运行。
  • 不会在非英特尔CPU中运行(但我想你已经考虑过这个了),如果你计划进行系统调用,你可能也需要针对特定​​的操作系统,这会失败Java的主要(被遗忘)目标之一。
  • 您可能需要一个自定义JVM才能直接运行本机指令。

这在理论上是可行的,但绝对不是一件小事。

如果您的意思是英特尔汇编程序或Java模拟器,那就是另一个故事。