【问题标题】:What will be the java equivalant code for the following code?以下代码的 java 等效代码是什么?
【发布时间】:2012-04-10 04:30:14
【问题描述】:

我正在使用 JNA 调用 user32.dll 和 kernel32.dll 的方法。到目前为止,它工作正常。我遇到了一些问题,我知道我必须调用这个方法。

void SendCommandToConsole( char* Cmd )
{
    DWORD dwCall = 0x004C1030;
    __asm
    {
        push Cmd;
        push 0;
        call dwCall;
    }
}

SendCommandToConsole ( "rp 2000" );

但我什至不明白它是什么?这个 __asm 在做什么?

如果我使用的标签不正确,请添加适当的标签。 :)

编辑 按照建议添加了 .Net 和 C# 标签。上面的代码是 C# 或 .NET,可能有这门语言知识的人可以告诉我们它到底是什么,以及我们如何在 java 中做到这一点。

【问题讨论】:

  • _asm 是内联汇编代码。它在堆栈上推送一个指向 C 等效字符串的指针,以 0 终止它,然后在 dwCall 地址调用该过程(我认为)。
  • 这看起来相当于System.out.println
  • @HovercraftFullOfEels 谢谢,我们能用java写类似的代码吗?
  • 从技术上讲,您可以,但您可能不想这样做。 JNA 可以构造回调,这是写入分配内存的可执行文件位。您可以获取回调可执行地址并将其覆盖,以便调用 JNA 回调将导致您的代码被执行。除非您真正了解汇编代码,否则不推荐。请注意,您的程序集 sn-p 不会公开编译器在访问传入参数或从 (C) 调用返回时生成的内容。
  • @RakeshJuyal 您问题中提供的代码 sn-p 不是 C#,而是普通 C。(C# 不允许您内联汇编。)我已相应地重新标记了您的问题.

标签: java c assembly jna equivalent


【解决方案1】:

只是为了展示幕后发生的事情:

您的电话:

SendCommandToConsole ("rp 2000");

正在使用 (char* Cmd) 类型的参数调用函数 (SendCommandToConsole)。

在上面的例子中,(char* Cmd) 等同于 "rp 2000" 的字符串 (sic)。

现在幕后发生的事情是,高级语言(在您的示例中是 Java)需要告诉低级语言如何用它们理解的语言解释它们的指令。

所以以上面的例子(“我想调用函数“SendCommandToConsole”,字符串参数为“rp 2000”),表示我们需要与低级语言进行通信:

  • “uppity-ups 想要我们运行命令”。 “哦,是的,是哪一个?”
  • “他们告诉我 'SendCommandToConsole'”
  • “哦,那个家伙?他住在下面的地址‘0x004C1030’。”
  • “哦,你知道那家伙的地址吗?你能把这个包裹送到 想要得到满足?”
  • “当然可以,但他只接受特定顺序的包裹,并且 只属于某种类型。”
  • “没问题,我这里有他们的清单……让我们看看有没有 符合老兄的要求。”

“首先,那个地址的家伙只想知道两件事,而且它们必须是有序的:

  • 你想让我做什么,
  • 我应该向谁报告结果?”

“好的,这很简单”

我会断言我想让他做什么:

  • “命令”
  • 现在我将断言我希望他向谁报告结果:“没有人 (0)”

好吧,我给他打电话……你可以继续你的一天了。

(因为是“无效”返回,表示你不关心交易的结果)

【讨论】:

    【解决方案2】:

    这意味着后面有一个汇编代码块。

    dwCall 是指向带有一个参数的汇编过程的指针 -> 指向堆栈上以零结尾的字节数组的指针。为了正确调用它,您必须将指针压入堆栈,并且只能通过汇编程序来完成。

    【讨论】:

    • 推送了两个参数。
    【解决方案3】:

    在 JNA 中,您可以使用 Function.getFunction(Pointer) 获取一个对象,您可以使用该对象来控制对特定地址的调用。

    Function dwCall = Function.getFunction(new Pointer(0x12345678));
    String CMD = "SomeCommand";
    Integer ARG = new Integer(0);
    dwCall.invoke(void.class, new Object[CMD, ARG]);
    

    假设函数使用 C 调用约定,上面的代码可以工作。最终,您可能希望动态查找函数地址而不是对其进行硬编码,并且您可能希望使用 JNA 回调而不是直接调用 Function 对象,但上面的代码提供了您所要求的基本功能for(你应该改写你原来的问题;你不想执行汇编代码,你想在给定的地址调用一个函数)。

    使用 JNA 回调映射将允许您更自然地调用函数。

    // Use StdCallCallback if the function called uses stdcall rather than cdecl
    public class MyCallback extends Callback {
        void invoke(String cmd, int arg);
    }
    
    Pointer addr = new Pointer(0x1235678);
    MyCallback cb = (MyCallback)CallbackReference.getCallback(MyCallback.class, addr);
    cb.invoke("SomeCommand", 0);
    

    请注意,这两个示例都假设您已经使用 JNA 加载了相关的 DLL,通常通过 Native.loadLibrary()

    还要注意签名实际上可能是void dwCall(int arg, String cmd); cdecl 和 stdcall 约定从右到左将参数推送到堆栈上,目前我的想法还不够清晰,无法正确映射...

    【讨论】:

    • 感谢@technomage,看起来很有希望:)。我会试试的。
    • 正如 Kaito 所指出的,调用序列似乎是 stdcall,因为调用后没有堆栈清理。如果它是 cdecl,那么您会在调用后看到堆栈调整(相当于两个“pop”)。但是,根据编译器在从“SendCommandToConsole”返回之前对询问语句所做的操作,可能并不严格要求进行此类清理,并且编写者只是忘记了清理。
    【解决方案4】:

    没有 Java 等价物,Java 不允许这种低级控制。需要将C代码编译成DLL,使用JNA/JNI调用。

    编辑 1:以上仅适用于一般的汇编代码。请参阅 techmage 对使用 JNA 在地址处调用 stdcall 或 cdecl 函数的回复。

    __asm 块允许您在 C 源文件中使用汇编。汇编代码调用地址为 0x004C1030 的函数(可能是任何函数),通过指针和零作为参数传递字符串。

    直接调用地址是个坏主意。除非您非常了解程序和操作系统的底层内部结构,否则您可能不会得到您期望的结果。调用它很可能会使您的程序崩溃。

    【讨论】:

    • 您关注的是 __asm 语句本身,而不是完整操作的整体结果。
    • 我们对调用的函数了解不多。我们可以只使用 stdcall ,因为调用方似乎没有清理,但这仍然只是希望它有效,它也可能是其他一些约定。我确实同意我应该更加明确并专注于实际示例。谢谢。
    【解决方案5】:

    你为什么不只是调用SendCommandToConsole() 函数?该函数所做的是进行 Windows 系统调用,您不应该编写执行此操作的函数,您应该调用执行此操作的函数。

    【讨论】:

    • 其实没有像sendCommandToConsole这样的方法,就像给定地址有一个方法,然后调用这个方法就可以任意命名了。我猜这是 .Net 或 c# 代码。
    • @RakeshJuyal,也许您应该在问题的 c# 或 .NET 或 windows 标记处,因为一旦您了解如何从普通 Windows 程序调用此函数,您应该能够让 JNA 映射它很容易。您偶然发现它的级别太低,需要更高级别的功能来提供对它的便携访问。
    【解决方案6】:

    我想真正的问题是“rp 2000”是做什么的?如果它使用参数 2000 运行 rp.exe,那么您可以使用 java.lang.Runtime 来做同样的事情。如果我们知道它做了什么,那么在 java 中可能会有一些东西来做。

    【讨论】:

    • 不,你甚至可以说 julian abc 而不是 rp 2000 。真正的问题是如何在给定的可执行文件中调用存储在地址0x004C1030 的方法。
    • 那么也许你应该改写你原来的问题来问“真正的问题”。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    相关资源
    最近更新 更多