C 使用x86 ASM在地址处存储的设置值
我试图让我的头围绕一些内联ASM,但出于某种原因,这不是我所期望的行为。为什么这个设置的x值不等于62C 使用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; } #包括
#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
将完全按照您的想法执行。