1

VSに関数があり、関数へのポインターを渡します。次に、ポインタをレジスタに格納してさらに操作したいと思います。どうやってそれをしますか?

私が試してみました

float __declspec(align(16)) x[16] = 
{
    0.125000, 0.125000, 0.125000, 0,
    -0.125000, 0.125000, -0.125000, 0,
    0.125000, -0.125000, -0.125000, 0,
    -0.125000, -0.125000, 0.125000, 0
};

void e()
{
    __asm mov eax, x // doesn't work
    __asm mov ebx, [eax]
}

void f(float *p)
{
    __asm mov eax, p // does work
    __asm mov ebx, [eax]
}

int main()
{
    f(x);
    e();
}
4

2 に答える 2

5

オプション1は実際にはうまくいくようです。次のプログラムを検討してください。

#include <stdio.h>

void f(int *p) {
    __asm mov eax, p
    __asm mov ebx, [eax]
    // break here
}

void main()
{
    int i = 0x12345678;
    f(&i);
}

Visual Studio 2008 SP1、単一ファイルの C++ プログラム、およびデバッグ ビルドでは、f() の最後にステップインすると、レジスタ ウィンドウに次のように表示されます。

EAX = 004DF960 
EBX = 12345678 
ECX = 00000000 
EDX = 00000001 
ESI = 00000000 
EDI = 004DF884 
EIP = 003013C3 
ESP = 004DF7B8 
EBP = 004DF884 
EFL = 00000202

EAX、EBX、および ESP の値を見ると、EAX で必要なポインターが実際にあるというかなり良い証拠のように見えます。EAX のアドレスは ESP のアドレスよりも少しだけ高く、スタックの 1 フレーム上にあることを示唆しています。EBX にロードされた参照解除された値は、正しいアドレスを取得したことを示しています。


グローバルのアドレスの読み込みは微妙に異なります。次の例では、LEA 命令を使用してタスクを実行します。

#include <stdio.h>

int a[] = { 0x1234, 0x4567 };

void main()
{
    // __asm mov eax, a    ; interpreted as eax <- a[0]
    __asm lea eax, a       ; interpreted as eax <- &a[0]
    __asm mov ebx, [eax]
    __asm mov ecx, [eax+4]
    // break here
}

main() の最後までステップ実行すると、次のレジスタ値が得られます。EAX は配列の最初の要素のアドレスを取得しますが、EBX と ECX はそのメンバーの値を取得します。

EAX = 00157038 
EBX = 00001234 
ECX = 00004567 
EDX = 00000001 
ESI = 00000000 
EDI = 0047F800 
EIP = 001513C9 
ESP = 0047F734 
EBP = 0047F800 
EFL = 00000202 

魔法は LEA 命令自体にはありません。むしろ、__asm ディレクティブは、MOV 命令と LEA 命令のどちらが使用されているかによって、C/C++ 識別子の扱いが異なるようです。これは、MOV 命令のコメントを外したときの同じプログラムの ASM ダンプです。LEA 命令がそのオフセットを取得する一方で、MOV 命令がその引数 (DWORD PTR) として a[] の内容を取得する方法に注意してください。

; ...

PUBLIC ?a@@3PAHA       ; a
_DATA SEGMENT
?a@@3PAHA DD 01234H    ; a
          DD 04567H
_DATA   ENDS

; ...

mov eax, DWORD PTR ?a@@3PAHA
lea eax, OFFSET ?a@@3PAHA
mov ebx, DWORD PTR [eax]
mov ecx, DWORD PTR [eax+4]

; ...
于 2010-06-03T03:10:15.550 に答える
1

これが正しいかどうかはわかりませんが、最初に *p を int にキャストしてから、その値をロードしようとしましたか?

void f(*p) { int tmp = (int)p; // asm stuff... }

于 2010-06-03T03:11:07.077 に答える