内联汇编器获取指针的地址 Visual Studio

Joe*_*Joe 1 assembly inline-assembly visual-studio visual-c++

我在 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();
}
Run Code Online (Sandbox Code Playgroud)

Ore*_*ner 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);
}
Run Code Online (Sandbox Code Playgroud)

使用 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
Run Code Online (Sandbox Code Playgroud)

查看 EAX、EBX 和 ESP 中的值,这看起来是一个很好的证据,表明您实际上在 EAX 中拥有所需的指针。EAX 中的地址仅比 ESP 中的地址高一点点,表明它在堆栈中高出一帧。加载到 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
}
Run Code Online (Sandbox Code Playgroud)

单步执行到 main() 的末尾可以获得以下寄存器值。EAX 获取数组中第一个元素的地址,而 EBX 和 ECX 获取其成员的值。

EAX = 00157038 
EBX = 00001234 
ECX = 00004567 
EDX = 00000001 
ESI = 00000000 
EDI = 0047F800 
EIP = 001513C9 
ESP = 0047F734 
EBP = 0047F800 
EFL = 00000202 
Run Code Online (Sandbox Code Playgroud)

魔法并不在于 LEA 指令本身。相反,__asm 指令根据使用的是 MOV 还是 LEA 指令,对 C/C++ 标识符的处理方式似乎有所不同。以下是同一程序的 ASM 转储,其中 MOV 指令未注释。请注意 MOV 指令如何获取 a[] 的内容作为其参数 (DWORD PTR),而 LEA 指令则获取其偏移量。

; ...

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]

; ...
Run Code Online (Sandbox Code Playgroud)