2

我一直在尝试调用 JNIEnv 函数 GetVersion(对于初学者),它的索引为 4(根据本网站)。

我一直在使用此站点作为参考,并通过使用 [ebp + x] 而不是参数名称将 masm 代码调整为 nasm。

下面的类和程序集文件应该创建一个乱码输出,但是一条错误消息将我引导到一个日志文件。
在这个非常大的日志文件中,我发现所谓的寄存器到内存映射似乎并没有将寄存器的内容识别为 JNIEnv 函数(在 eax 中)而是未知值,这一点特别有趣。

谁能告诉我我做错了什么?
我只会附加登录请求,因为它相当大。

Java代码:

public class Ver {
  private static native int ver();
  public static void main(String[] args) {
    System.loadLibrary("my32");
    System.out.println(ver());
  }
}

ASM 代码:

;my32.asm
segment .text
;JNIEXPORT void JNICALL Java_Ver_ver
;  (JNIEnv *, jclass);
global _Java_Ver_ver
_Java_Ver_ver:
    push ebp
    mov ebp, esp
    push ebx

    mov ebx, [ebp+8]
    mov eax, [ebx]

    mov ebx, eax
    mov eax, 4
    mov ecx, 4
    mul ecx
    add ebx, eax
    mov eax, [ebx]
    push dword [ebp+8]
    call [eax]

    pop ebx
    pop ebp
    ret 8
;assembled using nasm -fwin32 my32.asm
;linked using gcc -o my32.dll -shared my32.obj
;with mingw-gcc

希望这可以被认为是一个有趣的问题与 SSCE
您真诚地
mmm

4

1 回答 1

2

看起来你有太多的间接:

mov ebx, [ebp+8]   ; ebx = env
mov eax, [ebx]     ; eax = *env
...
mov eax, [ebx]     ; eax = (*env)->GetVersion
...
call [eax]         ; call *((*env)->GetVersion)

所以call应该是call eax(不带括号)。

此外,您可以删除您的抵消方法ebx,只需执行mov eax, [ebx + 16]. 或使用call [ebx + 16].

于 2014-05-10T11:38:25.633 回答