函数参数没有正确传入 MASM
Arguments to function not getting passed in correctly MASM
我正在学习 MASM,但我无法让这个简单的代码工作。我没有得到传递给调用的值,我不知道发生了什么。我试过 push 2,push 2,call pow。相同的结果。 EAX 和 EDX 看起来像垃圾或者内存地址。
线程 0x1544 已退出,代码为 -1073741510 (0xc000013a)。
线程 0xd8 已退出,代码为 -1073741510 (0xc000013a)。
线程 0x898 已退出,代码为 -1073741510 (0xc000013a)。
线程 0x21c4 已退出,代码为 -1073741510 (0xc000013a)。
程序“[2296] AssemblyTutorial.exe”已退出,代码为 -1073741510 (0xc000013a)。
这只是意味着我关闭了控制台window,但为什么有 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
将调用约定更改为 c 并且它可以工作,但我不知道为什么。如果有人能解释一下那就太好了。
使用 stdcall 调用约定,被调用方会清理堆栈...这就是我所知道的。肯定还有更多。从 pow 函数返回后,堆栈指针可以在任何位置继续,事情应该正常工作吧?
是的,cdecl和stdcall的区别在于前者是caller-clean,后者是callee-clean。 (另见 Raymond Chen's series on calling conventions in Windows。
问题是,您的 pow
过程不 遵循标准调用约定,因为它不 清理堆栈。作为 ret
指令的一部分,您需要指定要弹出的字节数。在这种情况下,那将是 ret 8
.
或者,您可以创建函数 cdecl,在这种情况下调用者负责清理堆栈,并且 MASM 可以自动生成此代码作为 INVOKE
指令的一部分。
why are there 4 threads?
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
我正在学习 MASM,但我无法让这个简单的代码工作。我没有得到传递给调用的值,我不知道发生了什么。我试过 push 2,push 2,call pow。相同的结果。 EAX 和 EDX 看起来像垃圾或者内存地址。
线程 0x1544 已退出,代码为 -1073741510 (0xc000013a)。 线程 0xd8 已退出,代码为 -1073741510 (0xc000013a)。 线程 0x898 已退出,代码为 -1073741510 (0xc000013a)。 线程 0x21c4 已退出,代码为 -1073741510 (0xc000013a)。 程序“[2296] AssemblyTutorial.exe”已退出,代码为 -1073741510 (0xc000013a)。
这只是意味着我关闭了控制台window,但为什么有 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
将调用约定更改为 c 并且它可以工作,但我不知道为什么。如果有人能解释一下那就太好了。
使用 stdcall 调用约定,被调用方会清理堆栈...这就是我所知道的。肯定还有更多。从 pow 函数返回后,堆栈指针可以在任何位置继续,事情应该正常工作吧?
是的,cdecl和stdcall的区别在于前者是caller-clean,后者是callee-clean。 (另见 Raymond Chen's series on calling conventions in Windows。
问题是,您的 pow
过程不 遵循标准调用约定,因为它不 清理堆栈。作为 ret
指令的一部分,您需要指定要弹出的字节数。在这种情况下,那将是 ret 8
.
或者,您可以创建函数 cdecl,在这种情况下调用者负责清理堆栈,并且 MASM 可以自动生成此代码作为 INVOKE
指令的一部分。
why are there 4 threads?
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