1

非常に特別な問題が発生しました。VMの場合、コードを命令関数からubyte配列にコピーしてから、この配列を実行する必要があります(この手法は、gccのインラインマクロvmと同様です)。基本的には、次のように機能します。

__gshared void * sp = null, sb = null; //stack pointer and stack base

__gshared void add() //the function is just there to access the instruction code
{
    asm{db "INSTRUCTIONCODESTART";} //this is a key to know where the instruction code starts

    //instruction code here (sample instruction add, pops 2 values from the stack and pushes its result)
    sp += 4;
    *cast(uint*)sp += *cast(uint*)(sp - 4);

    asm{db "INSTRUCTIONCODEEND";} //this is a key to know where instruction code ends
}

Initメソッドでは、すべての命令コードが独自のバッファーを取得し、バッファーには、INSTRUCTIONCODESTARTキーとINSTRUCTIONCODEENDキーの間のすべてのバイトがあります。この配列をWindowsのVirtualProtect呼び出しで実行可能にします。

これまでのところ、すべてが期待どおりに機能しますが、関数呼び出しを命令として実行しようとすると、エラーが発生します。

__gshared void testcall(){}

__gshared void call()
{
    asm{db "INSTRUCTIONCODESTART";} //this is a key to know where the instruction code starts

    //instruction code here (just calls a D function)
    testcall(); //this somehow throws an error

    asm{db "INSTRUCTIONCODEEND";} //this is a key to know where instruction code ends
}

ところで、私は次のコードで命令をテストしました

void instructiontest()
{
    uint dummy;
    ubyte[] buf = getFunctionCode(&add) ~ 0xC3; //gets code of instruction, appends 0xC3 at it ("ret" instruction, for test purposes only to see if it returns to the D code without errors)
    VirtualProtect(cast(void*)buf, buf.length, PAGE_EXECUTE_READWRITE, &dummy); //makes it executeable
    dummy = cast(uint)&buf[0];
    asm
    {
        call dummy[EBP];
    }
    print("instruction worked without errors!");
}

これまでのところ、すべての単純な命令(add、mul、sub、push0、push1、...)は機能しますが、関数呼び出しを使用して命令のコードを取得しようとすると、エラーがスローされます

私はどんな助けでも幸せでとても感謝しています。(ところで、スクリプト言語がDと通信できるようにするには、命令に関数呼び出しが必要です)

4

2 に答える 2

2

コードが何をしているのか、なぜコードが壊れているのかを明確に把握するには、コードを実際に分解する必要があります。call関数の逆アセンブルは次のとおりです。

0000000000414db8 <_D4test4callFZv>:
  414db8:   55                      push   rbp
  414db9:   48 8b ec                mov    rbp,rsp
  414dbc:   48 83 ec 08             sub    rsp,0x8
  414dc0:   53                      push   rbx
  414dc1:   41 54                   push   r12
  414dc3:   41 55                   push   r13
  414dc5:   41 56                   push   r14
  414dc7:   41 57                   push   r15
  414dc9:   49                      rex.WB
  414dca:   4e 53                   rex.WRX push rbx
  414dcc:   54                      push   rsp
  414dcd:   52                      push   rdx
  414dce:   55                      push   rbp
  414dcf:   43 54                   rex.XB push r12
  414dd1:   49                      rex.WB
  414dd2:   4f                      rex.WRXB
  414dd3:   4e                      rex.WRX
  414dd4:   43                      rex.XB
  414dd5:   4f                      rex.WRXB
  414dd6:   44                      rex.R
  414dd7:   45 53                   rex.RB push r11
  414dd9:   54                      push   rsp
  414dda:   41 52                   push   r10
  414ddc:   54                      push   rsp
  414ddd:   e8 ce ff ff ff          call   414db0 <_D4test8testcallFZv>
  414de2:   49                      rex.WB
  414de3:   4e 53                   rex.WRX push rbx
  414de5:   54                      push   rsp
  414de6:   52                      push   rdx
  414de7:   55                      push   rbp
  414de8:   43 54                   rex.XB push r12
  414dea:   49                      rex.WB
  414deb:   4f                      rex.WRXB
  414dec:   4e                      rex.WRX
  414ded:   43                      rex.XB
  414dee:   4f                      rex.WRXB
  414def:   44                      rex.R
  414df0:   45                      rex.RB
  414df1:   45                      rex.RB
  414df2:   4e                      rex.WRX
  414df3:   44                      rex.R
  414df4:   41 5f                   pop    r15
  414df6:   41 5e                   pop    r14
  414df8:   41 5d                   pop    r13
  414dfa:   41 5c                   pop    r12
  414dfc:   5b                      pop    rbx
  414dfd:   c9                      leave  
  414dfe:   c3                      ret    
  414dff:   90                      nop

414dc9開始マーカーが開始する414ddc場所、終了する場所(両端を含む)です。414de2終了マーカーが始まる場所、414df3終了する場所(両端を含む)です。だから、それを取り除いて、私たちは持っています:

0000000000414db8 <_D4test4callFZv>:
  414db8:   55                      push   rbp
  414db9:   48 8b ec                mov    rbp,rsp
  414dbc:   48 83 ec 08             sub    rsp,0x8
  414dc0:   53                      push   rbx
  414dc1:   41 54                   push   r12
  414dc3:   41 55                   push   r13
  414dc5:   41 56                   push   r14
  414dc7:   41 57                   push   r15
  ; code start marker here
  414ddd:   e8 ce ff ff ff          call   414db0 <_D4test8testcallFZv>
  ; code end marker here
  414df4:   41 5f                   pop    r15
  414df6:   41 5e                   pop    r14
  414df8:   41 5d                   pop    r13
  414dfa:   41 5c                   pop    r12
  414dfc:   5b                      pop    rbx
  414dfd:   c9                      leave  
  414dfe:   c3                      ret    
  414dff:   90                      nop

ここでは、プロローグとエピローグのコードをコピーしていないことは明らかです。しかし、それ自体は、ひどく問題になるべきではありません。

私はこのプログラムを試しました:

void main()
{
    foo();
}

void foo()
{
    auto addr = &bar;

    asm { call addr; }
}

void bar()
{
    asm { naked; call baz; ret; }
}

void baz()
{
}

わたしにはできる。率直に言って、あなたの問題がどこにあるのかわかりません。貼り付けたコードのほとんどは、ソースファイルにコピーしてコンパイルすることはできないため、何が問題になっているのかを判断するのは非常に困難です。ここにある情報のいくつかがお役に立てば幸いです。ほとんどの場合、デバッガーを接続して何が問題なのかを見つける必要があります。手を汚さずに、このような低レベルのものを台無しにすることを期待しないでください。;)

ところで、私はLinuxの64ビットx86でテストしました。

いずれにせよ、あなたがしていることは非常に移植性が低く、定義されていないなどです。注意してください。それはうまくいくかもしれませんが、あなたはゼロ保証で働いています。

于 2012-07-15T12:12:31.227 に答える
0

関連するすべてのコードの完全な逆アセンブルを見ずに、すべての間違いが何であるかを判断するのは難しいですが...

  1. x86コードは通常、位置に依存しません。つまり、別の場所にコピーしてそこで実行すると、失敗する可能性があり、ほとんどの場合失敗します。

  2. ebpほとんどの場合、レジスタ(およびを含むesp)とスタックの内容を破棄するコードをコピーしています。

于 2012-07-15T11:27:29.263 に答える