如果这个问题涉及过于基本的问题,请原谅我。
作为一个有点接近的人级程序员,我真的很想知道这一点 - 是否在编写应用程序时完全汇总了每个WIN API函数的基本代码,还是执行Win APIS停留的机器代码在内存中,由于PC被启动,并且只有该应用程序使用它们,因此在内存中是操作系统的一部分?
许多应用程序通过功能调用使用了所有操作系统的所有API。因此,我认为,并没有单独使用每个应用程序包含API机器代码,而只包含标题或签名来调用API,并且在启动应用程序时将映射API机器代码地址。
很抱歉,由于我的英语不好,我未能简洁地将这个问题简洁。我真的很想获得您的见解。谢谢。
If this question deals with too basic a matter, please forgive me.
As a somewhat-close-to-beginner-level programmer, I really wonder about this--whether the underlying code of every win API function is compiled altogether at the time of writing an app, or whether the machine code for executing win APIs stays in the memory as part of the OS since the pc is booted up, and only the app uses them?
All the APIs for an OS are used by many apps by means of function call. So I thought that rather than making every individual app include the API machine code on their own, apps just contain the header or signature to call the APIs and the API machine code addresses are mapped when launching the app.
I am sorry that I failed to make this question succinct due to my poor English. I really would like to get your insights. Thank you.
发布评论
评论(1)
系统的实现由系统通过编译模块提供(图像)。应用程序代码仅包含足够的信息,以便系统可以识别和加载所需的模块,并解决相应的导入。
例如,请考虑显示消息框的以下代码,等待其关闭,然后退出程序:
给定函数签名(在 hinuser.h 中声明,从 Windows.h )编译器可以几乎生成
呼叫
指令。它知道Callee期望它们的参数数量,预期类型以及订单和位置。缺少的是 user32.dll 内部的实际目标地址,仅在一个过程完全初始化后才知道,并将 user32.dll 模块映射到其地址空间中。显然,编译器直到加载时间后才能推迟代码生成。它需要生成
呼叫
指令现在。由于我们知道 “计算机科学中的所有问题都可以通过另一个层次来解决” em> 这也是编译器所做的:而不是发出直接呼叫指令,而是生成间接呼叫。不同之处在于,尽管直接呼叫需要立即提供目标地址,但间接呼叫可以指定存储目标地址的地址。In x86 assembly, instead of having to say
the compiler can conveniently delegate the call to the
避免了灾难,我们已经为我们购买了足够的时间来修复代码,然后才能实际执行。
创建过程对象后,系统将控制控制到其主要线程以完成初始化。该初始化的一部分是加载依赖项(例如 user32.dll 此处)。完成后,系统最终知道加载地址(以及最终导入的符号的地址,例如
_MessageBoxw@16
),并且可以在地址__ imp_emessageboxw@16
__ imp__messageboxw@16 <覆盖IAT条目。 /代码>带有导入的功能地址。
这就是系统如何为系统服务提供实现的方式,而无需客户应用程序知道(物理上)他们会在哪里找到它们。
我说“大约” ,因为事情在现实中更加参与。如果那是您想了解的东西,我将把它留给Raymond Chen。他已经发表了a seriper更多详细信息:
The implementation for (most) API calls is provided by the system by way of compiled modules (Portable Executable images). Application code only contains enough information so that the system can identify and load the required modules, and resolve the respective imports.
As an example consider the following code that shows a message box, waits for it to close, and then exits the program:
Given the function signature (declared in WinUser.h, which gets pulled in from Windows.h) the compiler can almost generate a
call
instruction. It knows the number of arguments, their expected types, and the order and location the callee expects them in. What's missing is the actual target address inside user32.dll, that's only known after a process was fully initialized, and had the user32.dll module mapped into its address space.Clearly, the compiler cannot postpone code generation until after load time. It needs to generate a
call
instruction now. Since we know that "all problems in computer science can be solved by another level of indirection" that's what the compiler does, too: Instead of emitting a direct call instruction it generates an indirect call. The difference is that, while a direct call immediately needs to provide the target address, an indirect call can specify the address at which the target address is stored.In x86 assembly, instead of having to say
the compiler can conveniently delegate the call to the Import Address Table (IAT):
Disaster averted, we've bought us just enough time to fix things up before the code actually executes.
Once a process object is created the system hands over control to its primary thread to finish initialization. Part of that initialization is loading dependencies (such as user32.dll here). Once that has completed, the system finally knows the load address (and ultimately the address of imported symbols, such as
_MessageBoxW@16
), and can overwrite the IAT entry at address__imp__MessageBoxW@16
with the imported function address.And that is approximately how the system provides implementations for system services without requiring client applications to know where (physically) they will find them.
I'm saying "approximately" because things are somewhat more involved in reality. If that is something you'll want to learn about, I'll leave it up to Raymond Chen. He has published a series of blog entries covering this topic in far more detail: