3

我最近一直在使用 Visual C++ 中的内联汇编,我想知道是否可以直接将值添加到堆栈上的局部变量,例如:

push 5
add [esp], 7

这样做可以吗?我在问因为我随机遇到了一些奇怪的问题(尽管大多数时候它工作正常),但是如果我通过一个寄存器我从来没有任何问题,就像这样:

push 5
mov eax, [esp]
add eax, 7
mov [esp], eax
4

1 回答 1

0

正如 Vlad Krasnov 在对该问题的评论中所说,问题来自编译器(和/或汇编器)不知道代码中参数的大小,例如add [esp], 7. 例如,如果您正在编写,则不会出现此问题add [esp], eax

如果你是编译器,你会如何解释这条指令?您被要求将 7 添加到 ESP 指向的内存位置。但既没有 7,也没有[esp]指定加法的参数有多大。一个字节?两个字节?四个字节?如果这不是内联汇编,甚至 8 个字节也是可能的(在 64 位代码中是不允许的。)

请注意,虽然 ESP 是 4 个字节,但它指向的内存位置可以是任意大小。立即数 7 也是如此,它可以容纳任意数量的字节。

Vlad Krasnov 在评论中再次提到的解决方案是明确指定操作数的大小。您可以查看您最喜欢的汇编器文档,但在这种情况下,如果您想要 32 位加法,您可以编写add DWORD PTR [esp], 7. 这显然表示[esp]指向内存中的 DWORD(MASM 为 32 位。)

另请注意,并非 x86 上的所有指令都支持其中包含立即值内存地址的形式。对于每条指令,您可以查看“ Intel Architectures Software Developer Manual ”,第 2 卷(这是指令集参考),以确保您尝试使用的指令确实存在!

而且,您应该始终检查编译器的汇编输出(因为您正在使用内联汇编)以确保编译器生成的代码实际上是您想要的。指示编译器生成汇编代码很容易,而且可读性很强!

于 2013-03-22T11:48:49.440 回答