我正在学习MASM,但我无法使用这个简单的代码。我没有得到我调用的值,我不知道发生了什么。我试过推2,推2,叫pow。结果相同。 EAX和EDX看起来像垃圾或内存地址。
线程0x1544已退出,代码为-1073741510(0xc000013a)。 线程0xd8已退出,代码为-1073741510(0xc000013a)。 线程0x898已退出,代码为-1073741510(0xc000013a)。 线程0x21c4已退出,代码为-1073741510(0xc000013a)。 程序'[2296] AssemblyTutorial.exe'已退出,代码为-1073741510(0xc000013a)。
这只是意味着我关闭了控制台窗口,但为什么有4个线程?
res
答案 0 :(得分:2)
是的,cdecl和stdcall之间的区别在于前者是调用者干净的而后者是被调用者干净的。 (另见Raymond Chen's series on calling conventions in Windows。
问题是,你的pow
程序是而不是遵循stdcall约定,因为它不清理堆栈。您需要指定要作为ret
指令的一部分弹出的字节数。在这种情况下,那将是ret 8
。
或者,您可以创建函数cdecl,在这种情况下调用者负责清理堆栈,MASM可以自动生成此代码作为INVOKE
指令的一部分。
为什么有4个帖子?
Windows出于各种原因启动后台线程。这些都不用担心。如果你进一步研究它们,你可能会发现它们是由线程池工作线程(ntdll.dll中的TppWorkerThread
)启动的。
对于它的价值,pow
函数可以更有效地编写为:
pow PROC x:DWORD, power:DWORD
; Load parameters into registers
mov eax, x
mov edx, power
mov ecx, eax
; Decrement 'power' by 1 and bail out if we're done.
dec edx
jz Finished
; The main loop.
CalculatePow:
imul eax, ecx
dec edx
jnz CalculatePow
Finished:
ret 8 ; assuming this function is STDCALL
pow ENDP
答案 1 :(得分:0)
将调用约定更改为c并且它可以正常工作,但我不知道为什么。如果有人能解释那会很棒。
使用stdcall调用约定,被调用者清理堆栈......这就是我所知道的。必须有更多。堆栈指针可以在从pow函数返回后的任何位置继续进行,并且事情应该正常工作吗?