Assembly 推送myVar、推送[myVar]和推送偏移myVar之间的差异

Assembly 推送myVar、推送[myVar]和推送偏移myVar之间的差异,assembly,reverse-engineering,masm,Assembly,Reverse Engineering,Masm,我是组装新手,正在使用MASM。 我看到这些代码行,想知道它们之间的区别是什么 a) push myVar b) push [myVar] c) push OFFSET myVar 我如何知道他们是否正在推送myVar的值或地址 谢谢 致以最良好的祝愿, 谢谢push myVar就是简单地将您的var推到堆栈上 push[myVar]正在解引用您的var。如果myVar是指针,此代码将在堆栈上的地址处推送值 我不确定最后一个,但它似乎正好相反,push OFFSET myVar将myVar

我是组装新手,正在使用MASM。 我看到这些代码行,想知道它们之间的区别是什么

a) push myVar

b) push [myVar]

c) push OFFSET myVar
我如何知道他们是否正在推送myVar的值或地址 谢谢

致以最良好的祝愿,
谢谢

push myVar
就是简单地将您的var推到堆栈上

push[myVar]
正在解引用您的var。如果myVar是指针,此代码将在堆栈上的地址处推送值


我不确定最后一个,但它似乎正好相反,
push OFFSET myVar
myVar
的地址推到堆栈上。

push myVar
只是将您的var推到堆栈上

push[myVar]
正在解引用您的var。如果myVar是指针,此代码将在堆栈上的地址处推送值


我不确定最后一个是否正确,但它似乎正好相反,
push OFFSET myVar
正在堆栈上推送
myVar
的地址。

这取决于您使用的汇编程序。对于MASM/TASM,前两个变量做同样的事情(将
myVar
的值推送到堆栈上),而第三个变量将
myVar
的地址推送到堆栈上(在分段模式下,即当前段内的偏移量)

换句话说,MASM/TASM假设您想要取消引用变量的有效地址,即使您在编写变量时没有括号。如果将立即数作为地址/操作数,则会有差异:

pushd 0             ; push the dword value 0 onto the stack
push dword ptr [0]  ; push the dword at address 0 onto the stack
                    ; will likely crash your program
与寄存器操作数类似:

push eax              ; push the value of eax onto the stack
push dword ptr [eax]  ; push the value at the address that eax points to

使用NASM,您可以将前两个变体编写为

push dword [myVar]  ; assuming a dword variable
第三个是

push myVar

这取决于您使用的汇编程序。对于MASM/TASM,前两个变量做同样的事情(将
myVar
的值推送到堆栈上),而第三个变量将
myVar
的地址推送到堆栈上(在分段模式下,即当前段内的偏移量)

换句话说,MASM/TASM假设您想要取消引用变量的有效地址,即使您在编写变量时没有括号。如果将立即数作为地址/操作数,则会有差异:

pushd 0             ; push the dword value 0 onto the stack
push dword ptr [0]  ; push the dword at address 0 onto the stack
                    ; will likely crash your program
与寄存器操作数类似:

push eax              ; push the value of eax onto the stack
push dword ptr [eax]  ; push the value at the address that eax points to

使用NASM,您可以将前两个变体编写为

push dword [myVar]  ; assuming a dword variable
第三个是

push myVar

假设我们的
数据
段声明如下:

.data
myVar DWORD 1, 5, 9
EAX = 00000001
不带[]

现在,让我们将其放入
code
部分:

.code
mov eax, myVar
如果我们现在查看寄存器(例如,通过调试器),我们可以看到如下内容:

.data
myVar DWORD 1, 5, 9
EAX = 00000001
与[]

我们可以像在C中使用
*
一样使用括号作为解引用运算符,因此如果我们现在将行更改为:

mov eax, [myVar]
我们得到:

EAX = 00000001
嗯…一样

但是现在我们可以想,哈!,如果将地址偏移量设置为
myVar
,我应该从myVar“array”中获取下一个值:

结果是:

EAX = 00000005
它起作用了!但是,如果我在没有括号的情况下做同样的事情呢

mov eax, myVar + 4
EAX = 00000005

嗯,同样的事情!因此,使用这两种符号必须没有区别。所以它们是完全等价的。

假设我们的
数据段声明如下:

.data
myVar DWORD 1, 5, 9
EAX = 00000001
不带[]

现在,让我们将其放入
code
部分:

.code
mov eax, myVar
如果我们现在查看寄存器(例如,通过调试器),我们可以看到如下内容:

.data
myVar DWORD 1, 5, 9
EAX = 00000001
与[]

我们可以像在C中使用
*
一样使用括号作为解引用运算符,因此如果我们现在将行更改为:

mov eax, [myVar]
我们得到:

EAX = 00000001
嗯…一样

但是现在我们可以想,哈!,如果将地址偏移量设置为
myVar
,我应该从myVar“array”中获取下一个值:

结果是:

EAX = 00000005
它起作用了!但是,如果我在没有括号的情况下做同样的事情呢

mov eax, myVar + 4
EAX = 00000005

嗯,同样的事情!因此,使用这两种符号必须没有区别。因此,它们是完全等效的。

“如果myVar是指针,则此代码将在堆栈上的地址处推送值。”实际上,它将执行与第一种情况完全相同的操作(推送
myVar的值)
)。确定。这意味着[]不重要。对吗?否。“push[var]-将地址var处的4个字节推送到堆栈上”。这意味着,如果var不是指针,可能会导致未定义的行为。何时声明的变量没有有效的地址?答案不清楚,Michael的答案要好得多。“如果myVar是指针,这段代码将在堆栈上的地址处推送值。”实际上,它将执行与第一种情况完全相同的操作(推送
myVar
)的值。好。这意味着[]不重要。对吗?否。“推送[var]-将地址var处的4个字节推送到堆栈上”。这意味着如果var不是指针,它可能会导致未定义的行为。何时声明的变量没有有效的地址?答案不清楚,Michael的答案要好得多。