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

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

问题描述

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

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.

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

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.

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

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?

在最纯粹的意义上,RET 指令不是比直接调用 ExitProcess() 更可取吗?直接调用 ExitProcess() 似乎类似于通过从任务管理器中终止程序来退出程序,因为这会短路返回到 Windows 加载程序调用入口点的位置的正常流程,从而跳过各种线程清理操作?

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.

推荐答案

如果您的 main 函数是从 C 运行时库调用的,那么退出将导致调用 ExitProcess() 并且进程将退出.

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.

如果您的 main 函数被 Windows 直接调用,就像汇编代码的情况一样,那么退出只会导致线程退出.进程将退出当且仅当没有其他线程.这是当今的一个问题,因为即使没有创建任何线程,Windows 可能已经代表您创建了一个或多个.

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.

据我所知,这种行为没有正确记录,但在 Raymond Chen 的博客文章中有所描述,"如果从主线程返回,进程是否退出?".

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?".

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

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

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

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天全站免登陆