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

C 使用x86 ASM在地址处存储的设置值,c,visual-c++,assembly,x86,inline-assembly,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; } #包括

我试图让我的头围绕一些内联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;
}
#包括
int main()
{
int x=525;
int*y=&x;
_asm
{
mov eax,62
mov[y],eax
}
printf(“%i”,x);
getchar();
返回0;
}
该代码导致525被输出。我希望是62。

您正在将
x
的地址加载到
y
中。然后将
62
存储在变量
y
的地址中(同样!)——这就是
[…]
语法的含义。因此,您不是在修改变量
x
,而是在*(*y)处存储的值。(这是一个不会使你的程序崩溃的小奇迹。)

你可能想要

mov [&y], eax

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

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

当然[y]的意思是[0xCCCC](假设x的地址是0xCCCC)

在高级理论中,是的。问题是,在实际汇编中,
[0xCCCC]
毫无意义-CPU不能直接取消对内存地址的引用-它只能将该地址中的值加载到寄存器中,然后取消对该地址的引用

类似地,由于
y
是一个变量,而不是寄存器,因此它被隐式地视为一个地址1,即
asm
块内的
y
相当于2外的C代码中的
&y
。通过在调试器中单步执行可以看出,所发生的情况是,汇编程序只是忽略了没有意义的括号(而不是抛出一个有用的错误),并组装了与
movy,eax
等效的代码

获得您期望的结果的方法如下:

asm {
    mov eax, 62
    mov edx, y
    mov [edx], eax
}
[1] 这显然不是GCC。GCC扩展asm是一个完全不同的球类游戏


[2] 有点简化——从C的角度来看,它是一个“地址”,但在汇编上下文中,它是一个内存操作数,更像是一个地址的使用。当我编译这篇文章时,
y
显示为
[ebp-20]
,从高级视图来看,它是“堆栈上的地址”。

你得到了什么结果?对不起,我应该说。。更新了问题。在我问问题之前我已经试过了,它不起作用。错误C2400:“第一个操作数”中的内联汇编程序语法错误;找到“AND”,当然[y]也意味着[0xcccc](假设x的地址是0xcccc)。因此[0xCCCC]==x。。对吗?谢谢,这会让事情变得更清楚一点,代码工作得很好。但是,根据您的解释,第二条指令,
mov-edx,y
不应该导致
y
的地址被复制到edx,而不是值吗?显然,我可以看到它确实在按值复制
y
,但是如果你说在
\u asm
块中,它实际上相当于C中的
&y
,为什么它不复制
y
的地址呢?希望这是有意义的…@user1727141我说“等效”,因为实际上并不存在1:1的对应关系-使用“地址”的方式取决于指令-
mov
只关心移动数据,所以使用内存操作数作为解引用的指针。要将地址本身放入寄存器,有一条“加载有效地址”指令:
lea-edx,y
将完全按照您的想法执行。