当您可以使用RET时,为什么在Win32下需要ExitProcess? [英] Why is ExitProcess necessary under Win32 when you can use a RET?

查看:96
本文介绍了当您可以使用RET时,为什么在Win32下需要ExitProcess?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到,许多使用直接Win32调用(无C运行时相关性)构建的汇编语言示例都说明了对ExitProcess()的显式调用的使用,以在入口点代码的末尾结束程序.我不是在谈论使用ExitProcess()在程序中的某些嵌套位置退出.出乎意料的是,只有很少的例子使用RET指令退出入口点代码.想到的一个例子是著名的 TinyPE ,程序变体以RET指令退出,因为RET指令是一个字节.都使用ExitProcess()或RET似乎都可以完成这项工作.

来自可执行文件入口点的RET将EAX的值返回到KERNEL32中的Windows加载器,该加载器最终将退出代码传播回NtTerminateProcess(),至少在Windows 7上如此.看到ExitProcess()甚至直接在线程清理链的末尾被调用.

由于在汇编语言中有许多受人尊敬的优化是纯粹在生成较小的代码时选择的,我想知道为什么更多的浮动代码更喜欢对ExitProcess()的显式调用,而不是RET.这是习惯还是其他原因?

从最纯粹的意义上讲,RET指令比直接调用ExitProcess()更好吗?直接调用ExitProcess()似乎类似于通过从任务管理器中杀死程序来退出程序,因为这会短路返回Windows加载器调用入口点的正常流程,从而跳过各种线程清理操作?/p>

我似乎找不到有关此问题的任何信息,所以我希望有人可以对此主题有所了解.

解决方案

如果从C运行时库中调用您的主要函数,则退出将导致对ExitProcess()的调用,并且该进程将退出.

如果主函数直接由Windows调用(汇编代码很可能就是这种情况),那么退出只会导致 thread 退出.当且仅当没有其他线程时,该进程才会退出.如今,这是一个问题,因为即使没有创建任何线程,Windows也可能代表您创建了一个或多个线程.

据我所知,此行为没有得到正确记录,但在Raymond Chen的博客文章如果您从主线程返回,进程会退出吗?".

(我自己也在Windows 7和Windows 10上进行了测试,并确认它们的行为符合Raymond的描述.)

附录:在Windows 10的最新版本中,进程加载器本身是多线程的,因此当进程首次启动时,总是存在其他线程./p>

I've noticed that many assembly language examples built using straight Win32 calls (no C Runtime dependency) illustrate the use of an explicit call to ExitProcess() to end the program at the end of the entry-point code. I'm not talking about using ExitProcess() to exit at some nested location within the program. There are surprisingly fewer examples where the entry-point code simply exits with a RET instruction. One example that comes to mind is the famous TinyPE, where the program variations exit with a RET instruction, because a RET instruction is a single byte. Using either ExitProcess() or a RET both seem to do the job.

A RET from an executable's entry-point returns the value of EAX back to the Windows loader in KERNEL32, which ultimately propagates the exit code back to NtTerminateProcess(), at least on Windows 7. On Windows XP, I think I remember seeing that ExitProcess() was even called directly at the end of the thread-cleanup chain.

Since there are many respected optimizations in assembly language that are chosen purely on generating smaller code, I wonder why more code floating around prefers the explicit call to ExitProcess() rather than RET. Is this habit or is there another reason?

In its purest sense, wouldn't a RET instruction be preferable to a direct call to ExitProcess()? A direct call to ExitProcess() seems akin to exiting your program by killing it from the task manager as this short-circuits the normal flow of returning back to where the Windows loader called your entry-point and thus skipping various thread cleanup operations?

I can't seem to locate any information specific to this issue, so I was hoping someone could shed some light on the topic.

解决方案

If your main function is being called from the C runtime library, then exiting will result in a call to ExitProcess() and the process will exit.

If your main function is being called directly by Windows, as may well be the case with assembly code, then exiting will only cause the thread to exit. The process will exit if and only if there are no other threads. That's a problem nowadays, because even if you didn't create any threads, Windows may have created one or more on your behalf.

As far as I know this behaviour is not properly documented, but is described in Raymond Chen's blog post, "If you return from the main thread, does the process exit?".

(I have also tested this myself on both Windows 7 and Windows 10 and confirmed that they behaved as Raymond describes.)

Addendum: in recent versions of Windows 10, the process loader is itself multi-threaded, so there will always be additional threads present when the process first starts.

这篇关于当您可以使用RET时,为什么在Win32下需要ExitProcess?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆