1

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 でこれを行う方法を教えてくれるかもしれません。

4

6 に答える 6

5

ボンネットの下で何が起こっているかを示すためだけに:

あなたの電話:

SendCommandToConsole (「rp 2000」);

タイプ (char* Cmd) のパラメーターを使用して関数 (SendCommandToConsole) を呼び出しています。

上記の場合、(char* Cmd) は「rp 2000」の文字列 (sic) に相当します。

隠れたところで起こっていることは、高水準言語 (あなたの例では Java) が低水準言語に、彼らが理解できる言語で命令を解釈する方法を伝える必要があるということです。

したがって、上記の例 (「関数 "SendCommandToConsole" を "rp 2000" の文字列パラメーターで呼び出したい) を例にとると、下位レベルの言語と通信する必要があることを意味します。

  • 「高揚者は私たちにコマンドを実行してもらいたい」. 「そうそう、どれ?」
  • 「彼らは私に「SendCommandToConsole」と言っています」
  • 「ああ、あの人?彼はここのアドレス「0x004C1030」に住んでいます。」
  • 「おや、男の住所を知っているか? 高潔な人たちが配達を望んでいるこの小包を届けてくれる?」
  • 「確かに、彼は特定の順序で、特定の種類のパッケージのみを受け入れます。」
  • 「問題ありません。ここにマニフェストがあります...それが男の要件に一致するかどうか見てみましょう。」

「まず最初に、その住所の男が知りたいことは 2 つだけで、それらがきちんと整理されていなければなりません。

  • どうしたいの?
  • 誰に結果を報告すればよいですか?」

「よし、簡単だ」

私は彼に何をしてもらいたいかを主張します:

  • 「コマンド」
  • ここで、誰に結果を報告してほしいかを断言します: "No one (0)"

よし、彼に電話するよ... もう一日を続けていいよ。

(取引の結果を気にしないという意味の「無効な」返品であるため)

于 2012-04-26T07:20:40.803 に答える
2

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 コールバックを使用したいと思うでしょうが、上記のコードは、求めている機能を提供します。 for (元の質問を言い換える必要があります。アセンブリ コードを実行したくない場合は、特定のアドレスで関数を呼び出したいと考えています)。

JNA Callback マッピングを使用すると、関数をより自然に呼び出すことができます。

// 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 規則は、スタック上のパラメーターを右から左にプッシュします。現時点では、それを適切にマップするのに十分なほど明確ではありません...

于 2012-04-30T15:42:20.003 に答える
2

これは、アセンブリ コード ブロックが続くことを意味します。

dwCall は、1 つの引数を取るアセンブリ プロシージャへのポインタ -> スタック上のゼロで終了するバイト配列へのポインタです。適切に呼び出すには、ポインターをスタックにプッシュする必要があります。これは、アセンブラーを介してのみ行うことができます。

于 2012-04-10T04:35:25.090 に答える
1

Javaに相当するものはありません。Javaでは、このような低レベルの制御は許可されていません。CコードをDLLとしてコンパイルし、JNA/JNIを使​​用して呼び出す必要があります。

編集1:上記は一般的なアセンブリコードにのみ当てはまります。JNAを使用してアドレスでstdcallまたはcdecl関数を呼び出すためのtechomageの応答を参照してください。

__asmブロックを使用すると、Cソースファイルでアセンブリを使用できます。アセンブリコードは、アドレス0x004C1030の関数(関数が何であれ)を呼び出し、文字列をポインタで渡し、ゼロを引数として渡します。

アドレスを直接呼び出すことは悪い考えです。プログラムとオペレーティングシステムの低レベルの内部を本当によく理解していない限り、おそらく期待どおりの結果が得られないでしょう。それを呼び出すと、プログラムがクラッシュする可能性があります。

于 2012-04-30T15:11:49.733 に答える
0

本当の問題は、「rp 2000」が何をするのかということだと思います。引数 2000 で rp.exe を実行する場合、java.lang.Runtime を使用して同じことを行うことができます。それが何をするかを知っていれば、それを行う何かが Java にあるかもしれません。

于 2012-04-28T20:30:46.160 に答える
0

SendCommandToConsole()関数を呼び出すだけではないのはなぜですか?その関数が行っていることは、Windows システム呼び出しを行うことであり、それを行う関数を作成するべきではありません。それを行う関数を呼び出す必要があります。

于 2012-04-25T23:24:19.633 に答える