现在,我使用汇编语言进行自学并使用MASM32。但是,我不了解一些代码行。我需要一个更好的解释。
mov eax,20
loop1:
push eax
invoke StdOut, addr HelloWorld
pop eax
dec eax
jnz loop1
如果没有推送和弹出,它将打印出'Hello World'无限!
我的问题:
为什么我们必须推送和弹出eax寄存器?
StdOut是否在内部更改该寄存器的值?
答案 0 :(得分:1)
因为对STDOUT
例程的调用会更改EAX
寄存器(也许这不是唯一的...)
是
答案 1 :(得分:1)
你说得对。在调用可能更改一个或多个寄存器的子例程之前,标准做法是在调用子例程之前将它们推送到堆栈中,它们将被保留。子程序返回后,以相反的顺序从堆栈中弹出值并将它们存储回原始寄存器。
答案 2 :(得分:0)
当您调用子程序无法保证您感兴趣的寄存器时,这是一种常见做法;所以,你将它们保存在堆栈(推送)并在通话后将它们取回(弹出)。
在某些情况下,可能会保留函数以保留一些寄存器,但“划伤”其他寄存器。当您知道存在此类约定时,您可以选择寄存器而不是其他寄存器以避免push/pop
模式。 (通过推送必须保留的寄存器,并在返回调用者之前弹出它们,简单地在被调用者中完成交易。)
E.g。当您在x86计算机上调用C标准库(“cdecl”calling-convention生效)的函数时,您需要保存“仅”eax
,ecx
和{{1}如果你需要保持他们的价值观。