2009-11-12 124 views
0

我在x86程序集上关注this tutorial。到目前为止,每个示例都使用作者称之为“C驱动程序”的程序,并使用程序集模块进行编译,以获得某些“初始化”。例如:x86汇编:主要序言和结语是什么?

int main(void) { 
    int ret = asm_main(); 
    return ret; 
} 

然后使用C调用约定正常写入asm_main函数。我想知道C编译器生成的所需初始化究竟是什么,以及是否可以以便携方式完成。

信息:我在Windows XP 32bit盒子上,使用NASM汇编器和mingw32-gcc进行链接。

回答

5

初始化不是由c编译器生成的,它是c库的一部分(这使得为每个操作系统/处理器定制操作变得更容易)。

有问题的代码通常在windows/unixy系统上非常简单 - 通常会执行一些库初始化(打开STDIN,STDOUT,STDERR,设置时区等),设置环境,处理命令行以传递给主要;捕获从main()返回并调用退出等。

大多数c库中的启动代码位于名为crt0.c,crt1.c或类似文件(crt = c运行时)的文件中。

在更原始或裸露的系统上,它也会设置堆栈和其他寄存器并清除BSS数据区 - 在这种情况下,它通常是汇编器(通常为crt0.S)。

这里是BSD的C启动代码的链接 - link text

而对于的MinGW的启动代码窗口中crt1.c这里 - http://mingw.cvs.sourceforge.net/viewvc/mingw/runtime/

+2

在一个C项目中,您所讨论的所有这些设置都是在main调用之前自动处理的(并且在主返回后自动退出事件)。 现在你可能会问,“什么是C项目?”。那么,这有点棘手的问题,但基本上,如果你有一个“主”功能和链接与libc(-lc)你正在作为一个C项目工作,即使你的代码中的每个功能都是用asm编写的。 –

0

你可以写你的主要装配,如果你想。但是很多人都希望将调试语句放在main中,并且在C中比在asm中更容易。

如果您在asm中编写main,您可能不得不处理main实际被调用的_main或使用替代调用约定(尤其是在Windows下)或其他奇怪的事情,例如C编译器在生成代码时自动处理的其他奇怪事情一个名为“main”的函数。这样做,所以你不必这样做。

0

在调用main()之前,必须初始化堆栈,寄存器和程序的文件段(data,rodata,bss等)。 C运行时库(CRT)提供了这个初始化。

CRT还提供了在每个函数被调用之前和之后执行的序言和尾声代码。序言和epilogue代码更新堆栈和帧指针。