函数调用后无法从汇编中返回main

时间:2017-07-31 14:39:31

标签: winapi assembly x86 return fasm

我正在使用fasm学习汇编,我在函数调用后无法从main返回。使用空程序,我可以使其正常工作

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语句失败,我该如何纠正呢?

1 个答案:

答案 0 :(得分:2)

进程中的初始线程基本上如下所示:

call LdrLoadAllTheThings ; Might call TLS callbacks etc
call pe_entrypoint ; Your function
push somenumber
call ExitThread ; Exit this thread and possibly the process

一个进程将在所有线程退出后结束,只是返回将适用于非常简单的程序但是只要有人调用CreateThread或其中一个线程池函数,当你刚刚返回时,进程将不再结束,只要有其他线程正在工作/等待,它就会坚持下去。在旧版本的Windows上,控制台程序通常可以返回,但正如您所发现的,它只能起作用,因为被调用的函数没有创建新线程(依赖于内部实现细节)。在GUI程序中,它更不可能工作并且难以调试,因为点击标准UI元素时PlaySound之类的东西可能会创建一个线程。

如果使用Microsoft工具链构建C / C ++应用程序并与其运行时库链接,那么主函数不是真正的入口点,真正的入口点是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
}