hus*_*sik 10 java assembly inline-assembly
我知道Java是一种安全的语言,但是当需要矩阵计算时,我可以更快地尝试一下吗?
我在C++,Digital-Mars编译器和FASM中学习__asm {}.我想在Java中做同样的事情.如何在函数中内联汇编代码?这甚至可能吗?
像这样的东西(使用AVX支持CPU将数组的所有元素钳制到没有分支的值的矢量化循环):
JavaAsmBlock(
# get pointers into registers somehow
# and tell Java which registers the asm clobbers somehow
vbroadcastss twenty_five(%rip), %ymm0
xor %edx,%edx
.Lloop: # do {
vmovups (%rsi, %rdx, 4), %ymm1
vcmpltps %ymm1, %ymm0, %ymm2
vblendvps %ymm2, %ymm0, %ymm1, %ymm1 # TODO: use vminps instead
vmovups %ymm1, (%rdi, %rdx, 4)
# TODO: unroll the loop a bit, and maybe handle unaligned output specially if that's common
add $32, %rdx
cmp %rcx, %rdx
jb .Lloop # } while(idx < count)
vzeroupper
);
System.out.println(var[0]);
Run Code Online (Sandbox Code Playgroud)
我不想使用代码注入器.我想看看英特尔或AT&T风格的x86指令.
Ern*_*ill 15
在Java代码和底层硬件之间有一层抽象,原则上使这种事情变得不可能; 从技术上讲,您无法知道代码在底层机器上的表示方式,因为相同的字节码可以在不同的处理器和不同的体系结构上运行.
您正式可以使用Java本机接口(JNI)从Java代码调用本机代码.调用开销很大,并且与Java共享数据相当昂贵,因此这应仅用于体面大小的本机代码块.
理论上,这种扩展应该是可能的.可以想象一个针对特定平台并允许程序集转义的Java编译器.编译器必须发布其ABI,因此您将了解调用约定.但是,我不知道有什么用.但是有几个 编译器 可以将Java直接编译为本机代码; 可能其中一个人在我不知情的情况下支持这样的事情,或者可以扩展到这样做.
最后,在一个不同的层面上,JVM有字节码汇编程序,如Jasmin.字节码汇编程序允许您编写直接面向JVM的"机器代码",有时您可以编写比javac编译器生成的代码更好的代码.无论如何,玩它很有趣.
您不能直接在Java代码中内联汇编.然而,与其他一些答案所声称的相反,方便地调用汇编而不经过任何中间C(或C++)层是可能的.
快速演练
考虑以下Java类:
public class MyJNIClass {
public native void printVersion();
}
Run Code Online (Sandbox Code Playgroud)
主要思想是使用JNI命名约定声明符号.在这种情况下,要在汇编代码中使用的错位名称是Java_MyJNIClass_printVersion.此符号必须在其他翻译单元中可见,例如可以使用publicFASM中的global指令或NASM中的指令来实现.如果您使用的是macOS,请在名称前加一个下划线.
使用目标体系结构的调用约定编写汇编代码(参数可以在寄存器,堆栈,其他内存结构等中传递).传递给汇编函数的第一个参数是一个指针JNIEnv,它本身是一个指向JNI函数表的指针.用它来调用JNI函数.例如,使用NASM并定位x86_64:
global Java_MyJNIClass_printVersion
section .text
Java_MyJNIClass_printVersion:
mov rax, [rdi]
call [rax + 8*4] ; pointer size in x86_64 * index of GetVersion
...
Run Code Online (Sandbox Code Playgroud)
可以在Java文档中找到JNI函数的索引.由于JNI函数表基本上是一个指针数组,因此不要忘记将这些索引乘以目标体系结构中指针的大小.
传递给汇编函数的第二个参数是对调用Java类或对象的引用.所有后续参数都是本机Java方法的参数.
最后,汇编代码以生成目标文件,然后从该目标文件创建共享库.GCC和Clang可以使用类似的命令执行最后一步gcc/clang -shared -o ....
其他资源
这篇DZone文章提供了更全面的演练.我还在GitHub上创建了一个完全可运行的示例,随意查看并使用它来更好地理解.