汇编,对堆栈上的局部变量进行算术运算

时间:2013-03-03 01:50:25

标签: assembly stack add

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

push 5
add [esp], 7

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

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

1 个答案:

答案 0 :(得分:0)

正如Vlad Krasnov在对该问题的评论中所说,问题来自于编译器(和/或汇编程序)不知道像add [esp], 7这样的代码中参数的大小。如果您正在编写add [esp], eax

,则不会出现此问题

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

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

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

另请注意,并非所有x86上的说明都支持具有内存地址的表单。对于每条指令,您可以查看“ Intel Architectures软件开发人员手册”,第2卷(这是指令集参考),以确保您尝试使用的指令确实存在!

并且,您应该始终检查编译器的程序集输出(因为您正在使用内联汇编)以确保编译器生成的代码实际上是您的意图。指示编译器生成汇编代码非常容易,并且它非常易读!