Closed. This question needs to be more
focused。它当前不接受答案。
想改善这个问题吗?更新问题,使其仅通过
editing this post专注于一个问题。
3年前关闭。
作为Linux的新手,我有一些问题:
如何从程序加载C运行时?
什么是路径和文件名?
在Windows上
C:\Windows\System32\msvcrt.dll
顺便说一句,在Linux上调用什么DLL?
MS
LoadLibrary
和
GetProcAddress
对应的功能是什么?
它们驻留在哪个DLL中?
我必须链接哪个库才能访问它们?
在Windows下,它是
kernel32.lib
和
kernel32.dll
。
最后:如何独立于目标平台编写Masm / JWasm代码?
是否有一个汇编程序符号可以反映命令行上使用的目标arg?
编辑:我忘了问几个问题:Linux是64位还是32位?它使用与64位MS C相同的调用约定吗?我的意思是rcx,rdx,r8,r9等中的参数。
典型的类UNIX系统将ELF文件格式用于目标文件,共享库和二进制文件。许多事情类似于Windows,但有些不同。首先,这里是常用后缀的列表:
UNIX Windows
*.o *.obj object file
*.a *.lib static library
*.so *.dll shared object (ELF targets)
*.dylib *.dll shared object (Mach O targets, i.e. Mac OS X)
* *.exe binary (no suffix on UNIX)
静态链接的工作方式与Windows大致相同,但动态链接却不同。首先,共享库没有lib文件。相反,当您要直接调用共享库时,静态链接程序
ld
会为您调用的每个函数生成带有存根的适当PLT(过程链接表)。在这种使用情况下,链接到的共享对象存储在二进制文件的特殊部分中。您的二进制文件不会直接执行,而是将动态加载程序
ld.so
作为二进制文件的解释器进行加载,查找所有需要的共享库并将它们加载到地址空间中。符号引用在首次调用时解析(除非您另有指定)。
您还可以使用
dl
库在运行时加载共享库,该库提供了功能
dlopen
,
dlclose
,
dlsym
和
dlerror
来加载共享库和访问其中的符号。请注意,
dl
库可能取决于libc的可用部分,因为所有系统调用都是通过libc完成的。在某些类似UNIX的操作系统上,libdl已集成到libc中。
当然,您也可以手动加载共享库,但这很复杂。
没有直接等同于Microsoft的
kernel32.dll
。系统调用在C标准库
libc.so
中实现(也可以在
libc.a
中静态使用),但是您也可以直接调用操作系统。汇编系统调用接口的稳定性在操作系统之间有所不同,但libc接口是稳定的。我强烈建议您使用libc独家调用操作系统。
当您通过C编译器链接时,CRT包含libc和几个目标文件,这些文件链接到您的程序中。这些目标文件从堆栈中检索参数向量和ELF辅助向量,然后调用libc。然后,libc为您调用
main
。我强烈建议您始终通过C编译器进行链接,并使汇编程序从
main
开始。这使得编程更加容易和可移植。
为了进一步阅读,建议您阅读
SysV ABI和有关ELF格式的文档。
如果要使用libc,建议您通过C编译器进行链接:
cc -o binary object1.o object2.o ... -llibrary1 -llibrary2 ...
这也将CRT入口存根链接到程序中。您的程序本身应提供一个名为
main
的全局符号,该符号由ABI的调用约定中的libc调用(在i386上,所有功能均使用cdecl,在amd64上使用SysV ABI调用约定)。签名如下:
main(argc, argv, envp);
其中
argc
是命令行参数的数量,argv是指向以Null结尾的命令行参数指针的数组的指针,envp是指向以Null结尾的环境变量数组的指针(每个条目的格式为< cc>。如果返回
key=value
,则C运行时将使用返回值
main
作为退出状态调用
exit
函数,请注意
main
刷新所有stdio缓冲区,因此您不必这样做。
您还可以使用
exit
选项创建静态二进制文件:
cc -static -o binary object1.o object2.o ... -llibrary1 -llibrary2 ...
请注意,某些libc功能(例如DNS查找)需要动态加载共享库,如果您使用这些功能中的任何一个,则可能在程序执行期间打开共享库。
如果不想使用libc,则将程序与链接器
-static
链接:
ld -o binary object1.o ... -llibrary1 ...
在这种情况下,程序的入口点是名为
ld
的全局符号,操作系统在启动时会在堆栈上放置一堆有用的东西,有关详细信息,请阅读上述ABI文档。
_start
,
stdin
和
stdout
分别可用作文件描述符0、1和2。不保证它们是打开的。您可以使用标准POSIX函数
stderr
和
read()
在它们之间进行数据读写。访问指向C
write()
结构
FILE
,
stdin
和
stdout
的指针取决于您为其编程的操作系统。在Linux上,这些只是外部符号,但在其他系统(例如FreeBSD)上,您可能需要调用函数来获取指针。