函数调用后无法 return from main in assembly
Cannot return from main in assembly after a function call
我正在使用 fasm 学习汇编,但在函数调用后从 main returning 遇到问题。使用空程序我可以让它正常工作
format PE console
entry start
include 'win32a.inc'
section '.text' code executable
start:
push ebp
mov ebp, esp
leave
ret
section '.rdata' data readable
format_str db '%d', 10, 0
section '.idata' data readable import
library msvcrt, 'msvcrt.dll'
import msvcrt, printf, 'printf'
但是如果我像这样添加一个函数调用(在本例中为 printf)
format PE console
entry start
include 'win32a.inc'
section '.text' code executable
start:
push ebp
mov ebp, esp
push esp
push format_str ;set to '%d',10,0 in the data section
call [printf]
add esp, 2*4
leave
ret
section '.rdata' data readable
format_str db '%d', 10, 0
section '.idata' data readable import
library msvcrt, 'msvcrt.dll'
import msvcrt, printf, 'printf'
程序会打印成功但会退出程序失败而崩溃
导致我的 return 语句失败的函数调用中发生了什么,我该如何纠正它?
进程中的初始线程基本上是这样的:
call LdrLoadAllTheThings ; Might call TLS callbacks etc
call pe_entrypoint ; Your function
push somenumber
call ExitThread ; Exit this thread and possibly the process
进程将在所有线程退出后结束,仅 returning 将适用于非常简单的程序,但一旦有人调用 CreateThread
或线程池函数之一,进程将不会当你只是 return 时,它就会更长,只要有其他线程在做 work/waiting,它就会一直存在。在旧版本的 Windows 上,控制台程序通常只 return 是可以的,但正如您所发现的,它之所以有效,是因为被调用的函数没有创建新线程(取决于内部实现细节)。在 GUI 程序中,它更不可能工作并且难以调试,因为单击标准 UI 元素时 PlaySound
之类的东西可能会创建一个线程。
如果您使用 Microsoft 工具链构建 C/C++ 应用程序并使用他们的运行时库构建 link 那么您的 main 函数不是真正的入口点,真正的入口点是 mainCRTStartup 并且它基本上是这样工作的:
__declspec(noreturn) void __cdecl mainCRTStartup()
{
int code;
char*argv;
int argc = parse(GetCommandLine(), &argv);
call_constructors();
code = main(argc, argv); // Your main function
call_destructors_and_atexit_callbacks();
ExitProcess(code); // End this thread and all other threads
}
我正在使用 fasm 学习汇编,但在函数调用后从 main returning 遇到问题。使用空程序我可以让它正常工作
format PE console
entry start
include 'win32a.inc'
section '.text' code executable
start:
push ebp
mov ebp, esp
leave
ret
section '.rdata' data readable
format_str db '%d', 10, 0
section '.idata' data readable import
library msvcrt, 'msvcrt.dll'
import msvcrt, printf, 'printf'
但是如果我像这样添加一个函数调用(在本例中为 printf)
format PE console
entry start
include 'win32a.inc'
section '.text' code executable
start:
push ebp
mov ebp, esp
push esp
push format_str ;set to '%d',10,0 in the data section
call [printf]
add esp, 2*4
leave
ret
section '.rdata' data readable
format_str db '%d', 10, 0
section '.idata' data readable import
library msvcrt, 'msvcrt.dll'
import msvcrt, printf, 'printf'
程序会打印成功但会退出程序失败而崩溃
导致我的 return 语句失败的函数调用中发生了什么,我该如何纠正它?
进程中的初始线程基本上是这样的:
call LdrLoadAllTheThings ; Might call TLS callbacks etc
call pe_entrypoint ; Your function
push somenumber
call ExitThread ; Exit this thread and possibly the process
进程将在所有线程退出后结束,仅 returning 将适用于非常简单的程序,但一旦有人调用 CreateThread
或线程池函数之一,进程将不会当你只是 return 时,它就会更长,只要有其他线程在做 work/waiting,它就会一直存在。在旧版本的 Windows 上,控制台程序通常只 return 是可以的,但正如您所发现的,它之所以有效,是因为被调用的函数没有创建新线程(取决于内部实现细节)。在 GUI 程序中,它更不可能工作并且难以调试,因为单击标准 UI 元素时 PlaySound
之类的东西可能会创建一个线程。
如果您使用 Microsoft 工具链构建 C/C++ 应用程序并使用他们的运行时库构建 link 那么您的 main 函数不是真正的入口点,真正的入口点是 mainCRTStartup 并且它基本上是这样工作的:
__declspec(noreturn) void __cdecl mainCRTStartup()
{
int code;
char*argv;
int argc = parse(GetCommandLine(), &argv);
call_constructors();
code = main(argc, argv); // Your main function
call_destructors_and_atexit_callbacks();
ExitProcess(code); // End this thread and all other threads
}