在 C 或汇编中制作一个简单的 CRT0

ali*_*ali 5 c++ assembly runtime crt

我回来了 C/C++ 和 ASM,我想玩一点火。我发现当您将代码编译并链接到 Windows 的可执行文件中时,它会动态链接到一些库,这些库必须存在于任何希望运行该应用程序的计算机上。您可以指定编译器不链接它们并为此创建自己的库。

除此之外(如果我在这里所说的一切都错了,请纠正我)还有一个目标文件,它总是沿着我们应用程序的主要代码编译和链接。它是 crt0.o(C 运行时)文件,据我所知,它准备堆栈、获取 argc 和 argv 并调用主函数(可能还有其他东西)。我也相信它是系统在执行应用程序时调用的第一段代码。

所以,我试图创建一个简单的 crt0.obj 并将它链接到一个简单的 C++ 对象文件

int main(int argc, char** argv) {
    return 0; 
}
Run Code Online (Sandbox Code Playgroud)

我使用 GCC 并且我不想使用标准库,所以我的命令看起来像:

g++ -s -nostartfiles -nodefaultlibs -nostdlib testapp.cpp -o test.exe crt0.o
Run Code Online (Sandbox Code Playgroud)

我想-nostartfiles指令是告诉链接器不要嵌入默认的 crt0.o,所以它希望我为任何函数提供每个定义并处理应用程序的启动。我在这里有点困惑。

无论如何,我想创建一个非常基本的 crt0 对象文件,这足以让 GCC 创建我的可执行文件,并让系统启动它。我知道 Internet 上有许多代码文件(C 和 ASM),但我想编写自己的代码文件以了解它的工作原理。我需要的不仅仅是代码,还有一些关于它必须做什么以及如何编译/链接以实现它的帮助。如果您知道任何有用的链接,也非常感谢。

我的疑问是:
1.编译器/链接如何从我的代码和 C 运行时创建最终文件?我是否必须从 crt0.o 调用 main 函数(使用 extern 指令)?当我执行时,g++ -s -nostartfiles -nodefaultlibs -nostdlib testapp.cpp -o test.exe我收到“*未定义对 __main* 的引用”错误。在crt0.o文件中定义了main函数吗?奇怪的是,如果我改变了int mainint start我没有收到任何错误。这意味着什么?
2. crt0 必须包含哪些基本操作(例如获取命令行参数、调用 main)?
3.我的代码文件是 CPP,crt0 是 C 文件中的一个程序集(用 GCC 编译)。我将发布一些我设法从我发现并部分理解的片段中创建的“frankencode”:

// crt0.c
__asm(".section .text\n" 
".global _start\n"
"_start:\n"
"mov $0, %ebp\n"
"push %ebp\n"
"mov %esp, %ebp\n"
"push %esi\n"
"push %edi\n"
"call _init\n"
"pop %edi\n"
"pop %esi\n"
"call main\n"
"movl %eax, %edi\n"
"call exit\n"
".section .init\n"
".global _init\n"
"_init:\n"
"push %ebp\n"
"mov %esp, %ebp\n"
".section .fini\n"
".global _fini\n"
"_fini:\n"
"push %ebp\n"
"mov %esp, %ebp\n");
Run Code Online (Sandbox Code Playgroud)

4.)所以,在这个文件中,我调用了一些初始化函数。init 和 fini 函数已经创建好了(它们看起来像简单的构造函数和析构函数,我不知道)还有 main 函数,我不知道它与 .cpp main 函数有什么关系。我的意思是,我应该导入它吗?我得到undefined reference两个主要和退出功能的错误。
5.) c0 必须有特定的格式或包含特定的函数才能让系统找到它的开始吗?

好吧,我认为制作一个小的 crt0 并使编译器将其附加到可执行文件并不困难,但是有些事情我无法正确查看。我希望有人能帮我把这一切整合在一起。谢谢

Mat*_*son 1

我没有 Windows 机器可供测试,但这应该是您需要的基本位:

#// crt0.c
__asm(".section .text\n" 
".global _start\n"
"_start:\n"
"mov $0, %ebp\n"
"push %ebp\n"
"mov %esp, %ebp\n"
"call main\n"
"pop  %ebp\n"
"ret\n");
Run Code Online (Sandbox Code Playgroud)

编辑:空__main

__asm(".global __main\n"
      "__main:\n" 
      "ret\n");
Run Code Online (Sandbox Code Playgroud)