【问题标题】:Inline assembler get address of pointer Visual Studio内联汇编程序获取指针 Visual Studio 的地址
【发布时间】:2010-06-03 02:13:03
【问题描述】:

我在 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();
}

【问题讨论】:

    标签: visual-studio visual-c++ assembly inline-assembly


    【解决方案1】:

    选项 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 中的地址高一点点,这表明它比堆栈高一帧。加载到 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 转储。注意 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]
    
    ; ...
    

    【讨论】:

    • 确实有效。抱歉,我的问题实际上是我无法加载指向全局数组指针的指针。你可以试试吗?我不想在堆栈上传递指针。
    • 不用担心。简而言之,使用 LEA 而不是 MOV。我添加到答案中。
    【解决方案2】:

    我不确定这是否正确,但您是否尝试过先将 *p 转换为 int 然后加载该值?

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-17
      • 2019-09-17
      • 1970-01-01
      相关资源
      最近更新 更多