函数的参数未正确传入 MASM



我正在学习MASM,但我无法让这个简单的代码工作。我没有得到我传递的值调用,我不知道发生了什么。我试过按 2、按 2、调用 pow。相同的结果。EAX 和 EDX 看起来像垃圾或内存地址。

线程0x1544已退出,代码为 -1073741510 (0xc000013a)。 线程0xd8已退出,代码为 -1073741510 (0xc000013a)。 线程0x898已退出,代码为 -1073741510 (0xc000013a)。 线程0x21c4已退出,代码为 -1073741510 (0xc000013a)。 程序 '[2296] AssemblyTutorial.exe' 已退出,代码为 -1073741510 (0xc000013a)。

这只是意味着我关闭了控制台窗口,但为什么有 4 个线程?

.386
.model flat,stdcall
option casemap:none
include windows.inc
include masm32.inc
includelib masm32.lib
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib

.code
;requires power > 0 for correct answers
pow proc x:DWORD, power:DWORD
;THESE TWO MOVES RIGHT HERE ARE NOT WORKING AS EXPECTED
;I PUSH 2 ONTO STACK BUT WHEN I LOOK AT REGISTER VALUES
;IN DEBUG THEY ARE INCORRECT/GARBAGE
mov eax, x      ;eax has x
mov edx, power  ;edx has power
mov ecx, eax    ;ecx will be my constant base
start_power:
cmp edx, 1      ;is power 1?
je end_power    ;then jump to end
imul eax, ecx   ;else mul result/x with x
dec edx         ;power--
jmp start_power ;jump back to beginning of loop
end_power:
ret             ;return answer eax
pow endp

start:
invoke pow, 2, 2 ;eax should hold 4 after this
invoke ExitProcess, eax ;program should exit with code eax, ez way to print result
end start

是的,cdecl 和 stdcall 之间的区别在于前者是调用方干净的,后者是被调用方干净的。(另请参阅Raymond Chen关于Windows中调用约定的系列文章。

问题是,您的pow程序没有遵循 stdcall 约定,因为它没有清理堆栈。您需要指定要作为ret指令的一部分弹出的字节数。在这种情况下,那将是ret 8.

或者,您可以创建函数 cdecl,在这种情况下,调用方负责清理堆栈,MASM 可以自动生成此代码作为INVOKE指令的一部分。

为什么有 4 个线程?

Windows 出于各种原因启动后台线程。这些都没什么可担心的。如果进一步调查它们,您可能会看到它们是由线程池工作线程(TppWorkerThread在 ntdll.dll 中启动的)。


对于它的价值,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

将调用约定更改为 c 并且可以工作,但我不知道为什么。如果有人能解释一下,那就太好了。

使用标准调用约定,被调用方清理堆栈...这就是我所知道的。它必须还有更多。堆栈指针可以在从 pow 函数返回后的任何位置继续前进,事情应该可以正常工作,对吗?

最新更新