使用x86 ASM设置存储在地址中的值

时间:2014-02-17 22:58:59

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

我试图绕过一些内联ASM,但由于某种原因,这不符合我的预期。为什么不设置x的值等于62?

#include <stdio.h>

int main()
{
    int x = 525;
    int* y = &x;

    _asm
    {
        mov eax, 62
        mov [y], eax
    }

    printf("%i", x);
    getchar();
    return 0;
}

代码导致输出525。我预计它会是62岁。

2 个答案:

答案 0 :(得分:2)

这里有一个完全可以理解的误解:

  

肯定[y]意味着[0xCCCCCCCC](假设x的地址是0xCCCCCCCC)

在高级理论中,是的。问题是,在实际汇编[0xCCCCCCCC]没有意义 - CPU不能直接取消引用内存地址 - 它只能从该地址加载一个值到一个寄存器中,然后取消引用< EM>那

同样,由于y变量,而不是寄存器,因此它被隐含地视为地址 1 ,即{{在y块内部,1}}相当于 2 之外的C代码中的asm。正如您在调试器中逐步看到的那样,发生了什么事情,汇编器只是忽略了没有意义的括号(而不是抛出一个有用的错误)并组装了等效的&y

获得你期望的方式将是这样的:

mov y, eax

[1]这显然不是GCC。 GCC扩展asm是一个整个不同的球赛......

[2]有点简化 - 从C的角度来看它是一个“地址”,但在汇编语境中它是一个内存操作数,它更像是地址的 use 。当我编译它时,asm { mov eax, 62 mov edx, y mov [edx], eax } 出现为y,从高级视图看来是“堆栈中的地址”。

答案 1 :(得分:0)

您将x地址加载到y。然后,您将62存储在变量 y地址(再次!)中 - 这就是[..]语法的含义。所以你不是修改变量x而是修改存储在*(* y)的值。 (并且这不会让你的程序崩溃,这是一个小小的奇迹。)

你可能想要

mov [&y], eax

(如果您的编译器接受该语法)。