我想知道我是否可以用C-programming语言编写一个可执行的程序,尽管不使用任何库调用,例如甚至不使用exit()?
如果是这样的话,它显然根本不依赖于库(libc、ld-linux)。
发布于 2009-02-08 00:42:39
我怀疑你可以写这样的东西,但它最终需要一个无限的循环,因为你不能要求操作系统退出你的进程。你不能做任何有用的事。
我们从编译ELF程序开始,研究ELF规范,并将程序所需的标题、程序段和其他部分组合在一起。内核会加载你的代码并跳转到某个初始地址。你可以在那里放置一个无尽的循环。但是,如果不了解某些汇编程序,从一开始就没有希望。
作为起点,glibc使用的start.S文件可能很有用。试着改变它,这样你就可以用它来组装一个独立的可执行文件。S文件是所有ELF应用程序的入口点,也是调用__libc_start_main的文件,而后者又调用main。您只需更改它,使其符合您的需求。
好吧,那只是理论上的。但现在,这有什么实际用途呢?
更新后的问题的答案
井。有一个名为libgloss的库,它为在嵌入式系统上运行的程序提供了最小的接口。newlib C库使用该库作为其系统调用接口。一般的想法是libgloss是C库和操作系统之间的一层。因此,它还包含操作系统跳转到的启动文件。这两个库都是GNU binutils项目的一部分。我使用它们为另一个操作系统和另一个处理器做接口,但是似乎没有一个用于Linux的libgloss端口,所以如果你调用系统调用,你将不得不自己做,就像其他人已经说过的那样。
用C编程语言编写程序是完全可能的。linux内核就是一个很好的例子。而且用户程序也是可能的。但最低限度需要的是一个运行时库(如果您想做任何重要的事情)。这样的函数将包含非常基本的函数,如memcpy、基本宏等。C标准有一种特殊的一致性模式,称为独立,它只需要一组非常有限的功能,也适用于内核。实际上,我对x86汇编器一无所知,但我已经尝试过一个非常简单的C程序:
/* gcc -nostdlib start.c */
int main(int, char**, char**);
void _start(int args)
{
/* we do not care about arguments for main. start.S in
* glibc documents how the kernel passes them though.
*/
int c = main(0,0,0);
/* do the system-call for exit. */
asm("movl %0,%%ebx\n" /* first argument */
"movl $1,%%eax\n" /* syscall 1 */
"int $0x80" /* fire interrupt */
: : "r"(c) :"%eax", "%ebx");
}
int main(int argc, char** argv, char** env) {
/* yeah here we can do some stuff */
return 42;
}我们很高兴,它实际上编译并运行:)
发布于 2009-02-08 00:25:42
是的,这是可能的,但是您必须进行系统调用并手动设置您的入口点。
带有入口点的最小程序示例:
.globl _start
.text
_start:
xorl %eax,%eax
incl %eax
movb $42, %bl
int $0x80或者在纯C语言中(无出口):
void __attribute__((noreturn)) _start() {
while(1);
}编译时使用:
gcc -nostdlib -o example example.s
gcc -nostdlib -o example example.c发布于 2009-02-08 01:13:09
用纯C语言?正如其他人所说的,你仍然需要一种方法来进行syscall,所以你可能需要下拉到内联asm。也就是说,如果使用的是gcc,请查看-ffreestanding。
https://stackoverflow.com/questions/524826
复制相似问题