函数调用后无法 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
}