flat assembler
Message board for the users of flat assembler.

Index > Examples and Tutorials > ASM + JAVA: Using JNI to access JAVA Objects from assembly.

Author
Thread Post new topic Reply to topic
typedef



Joined: 25 Jul 2010
Posts: 2914
Location: 0x77760000
typedef
So here's a tutorial of how to write native libraries for JAVA classes in Assembly using of course FASM.

I have a 64 bit OS so on 32-bit it should be straightforward.

I have included the JNI functions struct as well.

jni.inc
Code:
;
; Include file put together by typedef (board.flatassembler.net)
;

struct JNIEnv
       reserved0                               dq ?
       reserved1                               dq ?
       reserved2                               dq ?
       reserved3                               dq ?
       GetVersion                              dq ?
       DefineClass                             dq ?
       FindClass                               dq ?
       FromReflectedMethod                     dq ?
       FromReflectedField                      dq ?
       ToReflectedMethod                       dq ?
       GetSuperclass                           dq ?
       IsAssignableFrom                        dq ?
       ToReflectedField                        dq ?
       Throw                                   dq ?
       ThrowNew                                dq ?
       ExceptionOccurred                       dq ?
       ExceptionDescribe                       dq ?
       ExceptionClear                          dq ?
       FatalError                              dq ?
       PushLocalFrame                          dq ?
       PopLocalFrame                           dq ?
       NewGlobalRef                            dq ?
       DeleteGlobalRef                         dq ?
       DeleteLocalRef                          dq ?
       IsSameObject                            dq ?
       NewLocalRef                             dq ?
       EnsureLocalCapacity                     dq ?
       AllocObject                             dq ?
       NewObject                               dq ?
       NewObjectV                              dq ?
       NewObjectA                              dq ?
       GetObjectClass                          dq ?
       IsInstanceOf                            dq ?
       GetMethodID                             dq ?
       CallObjectMethod                        dq ?
       CallObjectMethodV                       dq ?
       CallObjectMethodA                       dq ?
       CallBooleanMethod                       dq ?
       CallBooleanMethodV                      dq ?
       CallBooleanMethodA                      dq ?
       CallByteMethod                          dq ?
       CallByteMethodV                         dq ?
       CallByteMethodA                         dq ?
       CallCharMethod                          dq ?
       CallCharMethodV                         dq ?
       CallCharMethodA                         dq ?
       CallShortMethod                         dq ?
       CallShortMethodV                        dq ?
       CallShortMethodA                        dq ?
       CallIntMethod                           dq ?
       CallIntMethodV                          dq ?
       CallIntMethodA                          dq ?
       CallLongMethod                          dq ?
       CallLongMethodV                         dq ?
       CallLongMethodA                         dq ?
       CallFloatMethod                         dq ?
       CallFloatMethodV                        dq ?
       CallFloatMethodA                        dq ?
       CallDoubleMethod                        dq ?
       CallDoubleMethodV                       dq ?
       CallDoubleMethodA                       dq ?
       CallVoidMethod                          dq ?
       CallVoidMethodV                         dq ?
       CallVoidMethodA                         dq ?
       CallNonvirtualObjectMethod              dq ?
       CallNonvirtualObjectMethodV             dq ?
       CallNonvirtualObjectMethodA             dq ?
       CallNonvirtualBooleanMethod             dq ?
       CallNonvirtualBooleanMethodV            dq ?
       CallNonvirtualBooleanMethodA            dq ?
       CallNonvirtualByteMethod                dq ?
       CallNonvirtualByteMethodV               dq ?
       CallNonvirtualByteMethodA               dq ?
       CallNonvirtualCharMethod                dq ?
       CallNonvirtualCharMethodV               dq ?
       CallNonvirtualCharMethodA               dq ?
       CallNonvirtualShortMethod               dq ?
       CallNonvirtualShortMethodV              dq ?
       CallNonvirtualShortMethodA              dq ?
       CallNonvirtualIntMethod                 dq ?
       CallNonvirtualIntMethodV                dq ?
       CallNonvirtualIntMethodA                dq ?
       CallNonvirtualLongMethod                dq ?
       CallNonvirtualLongMethodV               dq ?
       CallNonvirtualLongMethodA               dq ?
       CallNonvirtualFloatMethod               dq ?
       CallNonvirtualFloatMethodV              dq ?
       CallNonvirtualFloatMethodA              dq ?
       CallNonvirtualDoubleMethod              dq ?
       CallNonvirtualDoubleMethodV             dq ?
       CallNonvirtualDoubleMethodA             dq ?
       CallNonvirtualVoidMethod                dq ?
       CallNonvirtualVoidMethodV               dq ?
       CallNonvirtualVoidMethodA               dq ?
       GetFieldID                              dq ?
       GetObjectField                          dq ?
       GetBooleanField                         dq ?
       GetByteField                            dq ?
       GetCharField                            dq ?
       GetShortField                           dq ?
       GetIntField                             dq ?
       GetLongField                            dq ?
       GetFloatField                           dq ?
       GetDoubleField                          dq ?
       SetObjectField                          dq ?
       SetBooleanField                         dq ?
       SetByteField                            dq ?
       SetCharField                            dq ?
       SetShortField                           dq ?
       SetIntField                             dq ?
       SetLongField                            dq ?
       SetFloatField                           dq ?
       SetDoubleField                          dq ?
       GetStaticMethodID                       dq ?
       CallStaticObjectMethod                  dq ?
       CallStaticObjectMethodV                 dq ?
       CallStaticObjectMethodA                 dq ?
       CallStaticBooleanMethod                 dq ?
       CallStaticBooleanMethodV                dq ?
       CallStaticBooleanMethodA                dq ?
       CallStaticByteMethod                    dq ?
       CallStaticByteMethodV                   dq ?
       CallStaticByteMethodA                   dq ?
       CallStaticCharMethod                    dq ?
       CallStaticCharMethodV                   dq ?
       CallStaticCharMethodA                   dq ?
       CallStaticShortMethod                   dq ?
       CallStaticShortMethodV                  dq ?
       CallStaticShortMethodA                  dq ?
       CallStaticIntMethod                     dq ?
       CallStaticIntMethodV                    dq ?
       CallStaticIntMethodA                    dq ?
       CallStaticLongMethod                    dq ?
       CallStaticLongMethodV                   dq ?
       CallStaticLongMethodA                   dq ?
       CallStaticFloatMethod                   dq ?
       CallStaticFloatMethodV                  dq ?
       CallStaticFloatMethodA                  dq ?
       CallStaticDoubleMethod                  dq ?
       CallStaticDoubleMethodV                 dq ?
       CallStaticDoubleMethodA                 dq ?
       CallStaticVoidMethod                    dq ?
       CallStaticVoidMethodV                   dq ?
       CallStaticVoidMethodA                   dq ?
       GetStaticFieldID                        dq ?
       GetStaticObjectField                    dq ?
       GetStaticBooleanField                   dq ?
       GetStaticByteField                      dq ?
       GetStaticCharField                      dq ?
       GetStaticShortField                     dq ?
       GetStaticIntField                       dq ?
       GetStaticLongField                      dq ?
       GetStaticFloatField                     dq ?
       GetStaticDoubleField                    dq ?
       SetStaticObjectField                    dq ?
       SetStaticBooleanField                   dq ?
       SetStaticByteField                      dq ?
       SetStaticCharField                      dq ?
       SetStaticShortField                     dq ?
       SetStaticIntField                       dq ?
       SetStaticLongField                      dq ?
       SetStaticFloatField                     dq ?
       SetStaticDoubleField                    dq ?
       NewString                               dq ?
       GetStringLength                         dq ?
       GetStringChars                          dq ?
       ReleaseStringChars                      dq ?
       NewStringUTF                            dq ?
       GetStringUTFLength                      dq ?
       GetStringUTFChars                       dq ?
       ReleaseStringUTFChars                   dq ?
       GetArrayLength                          dq ?
       NewObjectArray                          dq ?
       GetObjectArrayElement                   dq ?
       SetObjectArrayElement                   dq ?
       NewBooleanArray                         dq ?
       NewByteArray                            dq ?
       NewCharArray                            dq ?
       NewShortArray                           dq ?
       NewIntArray                             dq ?
       NewLongArray                            dq ?
       NewFloatArray                           dq ?
       NewDoubleArray                          dq ?
       GetBooleanArrayElements                 dq ?
       GetByteArrayElements                    dq ?
       GetCharArrayElements                    dq ?
       GetShortArrayElements                   dq ?
       GetIntArrayElements                     dq ?
       GetLongArrayElements                    dq ?
       GetFloatArrayElements                   dq ?
       GetDoubleArrayElements                  dq ?
       ReleaseBooleanArrayElements             dq ?
       ReleaseByteArrayElements                dq ?
       ReleaseCharArrayElements                dq ?
       ReleaseShortArrayElements               dq ?
       ReleaseIntArrayElements                 dq ?
       ReleaseLongArrayElements                dq ?
       ReleaseFloatArrayElements               dq ?
       ReleaseDoubleArrayElements              dq ?
       GetBooleanArrayRegion                   dq ?
       GetByteArrayRegion                      dq ?
       GetCharArrayRegion                      dq ?
       GetShortArrayRegion                     dq ?
       GetIntArrayRegion                       dq ?
       GetLongArrayRegion                      dq ?
       GetFloatArrayRegion                     dq ?
       GetDoubleArrayRegion                    dq ?
       SetBooleanArrayRegion                   dq ?
       SetByteArrayRegion                      dq ?
       SetCharArrayRegion                      dq ?
       SetShortArrayRegion                     dq ?
       SetIntArrayRegion                       dq ?
       SetLongArrayRegion                      dq ?
       SetFloatArrayRegion                     dq ?
       SetDoubleArrayRegion                    dq ?
       RegisterNatives                         dq ?
       UnregisterNatives                       dq ?
       MonitorEnter                            dq ?
       MonitorExit                             dq ?
       GetJavaVM                               dq ?
       GetStringRegion                         dq ?
       GetStringUTFRegion                      dq ?
       GetPrimitiveArrayCritical               dq ?
       ReleasePrimitiveArrayCritical           dq ?
       GetStringCritical                       dq ?
       ReleaseStringCritical                   dq ?
       NewWeakGlobalRef                        dq ?
       DeleteWeakGlobalRef                     dq ?
       ExceptionCheck                          dq ?
       NewDirectByteBuffer                     dq ?
       GetDirectBufferAdqress                  dq ?
       GetDirectBufferCapacity                 dq ?
       GetObjectRefType                        dq ?
ends
    


<dll_name>.asm (mine is libNative)
Code:
format PE64 GUI 4.0 DLL at 0x10000000 ; Force base address

include 'win64a.inc'
include 'jni.inc'

section '.data' data readable

align 8

hello   db 'String from java = "%s"',0Dh,0Ah,00
unicode du 'Hello World from Assembly',0Dh,0Ah,00
len = $ - unicode

section '.text' code readable executable

proc sayHello ;    JNIEnv *env, jobject obj, jstring string
     push   rbx
     push   rsi
     push   rdi        ; rcx = env, rdx = obj, r8 = jstring,

     push    rdx       ; pointer to this class

     sub    rsp,0x20   ; not used here

     mov    rbx, [rcx]

     virtual at rbx
         env JNIEnv
     end virtual

    ; get C string from JAVA Object
     mov    rdi, r8                   ; save jstring
     mov    rdx, r8                   ; String object to get string from
     xor    r8,  r8                   ; null
    ;mov    rcx, env                  ; rcx is already JNIEnv
     call   [env.GetStringUTFChars]   ; RAX = const char *;

     mov     rsi, rax                 ; save returned pointer to char *

     mov     rdx, rax
     mov     rcx, hello               ; Awww My Gewdness ! No stack cleaning ?
     call    [printf]

    ; free C string
     mov     r8, rsi
     mov     rdx, rdi
     mov     rcx, rbx
     call    [env.ReleaseStringUTFChars]

     add    rsp,0x20

     pop     rax        ; return pointer to self

     pop    rdi
     pop    rsi
     pop    rbx
     ret
endp

proc getString ;    JNIEnv *env, jobject obj
     push   rbx
     push   rsi
     push   rdi

     mov    rbx, [rcx]

     virtual at rbx
         jni JNIEnv
     end virtual

     ; create java.lang.String
     mov    r8, len
     mov    rdx, unicode
     call   [jni.NewString]

     pop    rdi
     pop    rsi
     pop    rbx

     ret
endp

section '.idata' import data readable

  library msvcrt,'msvcrt.dll'

  import msvcrt,\
         printf,'printf'

section '.edata' export data readable

  export 'libNative.DLL',\
         sayHello,'Java_com_typedef_jnitest_callAssembly',\
         getString,'Java_com_typedef_jnitest_getString'

    


java source. Must be in appropriate package of course or remove the package and change the exported function names as well

Code:
package com.typedef;

public class jnitest {
    
    /**
     * Returns the same object
     * @param string
     * @return jnitest
     */
    private native jnitest callAssembly(String s);
    private native String getString();
    
   static{
      System.loadLibrary("libnative");   /* DLL name. Note lowercase of classname! Must be in same directory or absolute path */
   }
    
    public static void main(String ... args){     
        System.out.println(
                new jnitest().callAssembly("hello world from java").getString()
        );
    }
}
    


If you're not familiar with JNI or JAVA here's a read: http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/jniTOC.html

EDIT: ???


Last edited by typedef on 25 May 2014, 20:39; edited 1 time in total
Post 19 Jun 2013, 13:24
View user's profile Send private message Reply with quote
TmX



Joined: 02 Mar 2006
Posts: 820
Location: Jakarta, Indonesia
TmX
And what changes should I make so the example can be run in 32-bit OS?
Changing rsp to esp, rdi to edi, rax to ,eax, and so on?
And what about r8?
Post 20 Jun 2013, 06:31
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2914
Location: 0x77760000
typedef
TmX wrote:
And what changes should I make so the example can be run in 32-bit OS?
Changing rsp to esp, rdi to edi, rax to ,eax, and so on?
And what about r8?


That's x64's calling convention. On x86 you just push.

When calling a function

rcx = 1st parameter
rdx = 2nd
r8 = 3rd ''
r9 = 4th ''

On 32-bit you push the parameters on stack.

push 4th
push 3rd
....

etc

Also, in jni.inc replace all occurrences of dq with dd.

Another thing is you should also remove the forced base address on line format PE64 GUI 4.0 DLL at 0x10000000 ; Force base address so it becomes format PE GUI 4.0 DLL
Post 20 Jun 2013, 09:27
View user's profile Send private message Reply with quote
TmX



Joined: 02 Mar 2006
Posts: 820
Location: Jakarta, Indonesia
TmX
I mean things like:
Code:
mov    rdi, r8                   ; save jstring
mov    rdx, r8                   ; String object to get string from
xor    r8,  r8                   ; null     


What's the 32-bit equivalent?
And thanks for the other tips Very Happy
Post 21 Jun 2013, 04:10
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2914
Location: 0x77760000
typedef
On 32 bit. You don't need to actually save the pointers in registers since they're already passed on through the stack.

Code:

push 0
push dword[ebp+0x10]  ; Our 2rd parameter on the stack, (The String object), r8 on x64
push dword[ebp+0x8]  ; Our 1st parameter on the stack (The JNIEnv structure pointer)
call   [env.GetStringUTFChars]

; Function we are calling  = const char * GetStringUTFChars(JNIEnv *env, jstring string,jboolean *isCopy);
 
    


Also, I'm sure you're familiar with the C calling convention. On 32 bit you'll need to clean the stack after calling the printf function.

I'll see if I can create a 32-bit VM and make a 32-bit version if you have more questions.
Post 21 Jun 2013, 05:35
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2019, Tomasz Grysztar.

Powered by rwasa.