⬆️ ⬇️

Interoperability Java and ... Assembler?

In Java, it is possible to use software code implemented in other programming languages, the so-called JNI . You can write a dynamically linked library, then load it in Java code, and use functions from there by declaring them as the native methods of the class that loaded it. JNI was created primarily to perform machine-dependent actions (and also, possibly, improve the performance of speed-critical parts of an application) in C / C ++, but no one bothers to write the library in assembly language.



Tools



To create this perversion, Windows, Oracle JDK, Yasm (without macros) and the linker from Microsoft Visual Studio 2010 were used. If you wish, it would not be difficult to replace any of these components with your favorite, I tried not to use any non-standard features.



Using JNI



To begin with, let's create a Java class in which the function from the future .dll will be called:



public class TestJNI { native static int sum(int x, int y); //   sum public static void main(String[] args) { System.loadLibrary("mydll"); //   mydll.dll System.out.println(sum(2, 3)); //   } } 


')

Name Mangling in Java



Now you need to know what function name the Java machine is looking to find in our library. Let's use for this the javah program from JDK:



javac TestJNI.java

javah TestJNI





This will generate a C ++ header:

 /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class TestJNI */ #ifndef _Included_TestJNI #define _Included_TestJNI #ifdef __cplusplus extern "C" { #endif /* * Class: TestJNI * Method: sum * Signature: (II)I */ JNIEXPORT jint JNICALL Java_TestJNI_sum (JNIEnv *, jclass, jint, jint); #ifdef __cplusplus } #endif #endif 




The information contained here is needed mainly for the further writing of the library in C ++, we are only interested in the function signature:



 JNIEXPORT jint JNICALL Java_TestJNI_sum (JNIEnv *, jclass, jint, jint); 




We see that in the dll function must have the name JNICALL Java_TestJNI_sum and take 4 parameters. For the simplest functions, we will not need the first two of them. Any strange data types like JNIEXPORT, as it is easy to guess, are declared in the jni.h file, which is part of the JDK.



Assembler



Now let's write the library:



 ;mydll.asm section .text global Java_TestJNI_sum Java_TestJNI_sum: mov eax, [esp + 12] ;   2  add eax, [esp + 16] ret 16 end 




 ;mydll.def LIBRARY mydll EXPORTS Java_TestJNI_sum 




Compile and link:

yasm -f win32 mydll.asm

link /SUBSYSTEM:windows /DLL /NOENTRY /DEF:mydll.def mydll.obj





At the output we get a .dll file, which we need to pass to the code in Java.



Result



Put the files mydll.dll and TestJNI.class in one folder and see what happened:



>java TestJNI

5





This is a victory, we have learned to add two numbers!



If suddenly someone became interested, then the following links will be useful to him:



Source: https://habr.com/ru/post/145804/



All Articles