我想知道我是否可以用C
可执行的-programming 语言编写一个程序,尽管不使用单个库调用,例如甚至不使用exit()?
如果是这样,它显然根本不依赖库(libc、ld-linux)。
我想知道我是否可以用C
可执行的-programming 语言编写一个程序,尽管不使用单个库调用,例如甚至不使用exit()?
如果是这样,它显然根本不依赖库(libc、ld-linux)。
我怀疑你可以写这样的东西,但它最后需要有一个无限循环,因为你不能要求操作系统退出你的进程。你不能做任何有用的事情。
从编译 ELF 程序开始,查看 ELF 规范并将标题、程序段和程序所需的其他部分一起制作。内核将加载您的代码并跳转到某个初始地址。你可以在那里放置一个无限循环。但是,如果不了解一些汇编程序,无论如何从一开始就是没有希望的。
glibc 使用的start.S
文件可以作为一个有用的起点。尝试更改它,以便您可以从中组装一个独立的可执行文件。该 start.S 文件是所有 ELF 应用程序的入口点,并且是调用__libc_start_main
该文件的那个,而该文件又调用main
. 您只需更改它以使其适合您的需求。
好吧,那是理论上的。但是现在,它有什么实际用途呢?
好。有一个名为的库libgloss
,它为旨在在嵌入式系统上运行的程序提供最小接口。newlib
C 库使用它作为其系统调用接口。总体思路是 libgloss 是 C 库和操作系统之间的层。因此,它还包含操作系统跳转到的启动文件。这两个库都是 GNU binutils 项目的一部分。我用它们为另一个操作系统和另一个处理器做接口,但似乎没有用于 Linux 的 libgloss 端口,所以如果你调用系统调用,你将不得不自己做,正如其他人已经说过的那样.
用 C 编程语言编写程序是绝对可能的。linux 内核就是这样一个程序的一个很好的例子。但用户程序也是可能的。但最低限度需要的是一个运行时库(如果你想做任何严肃的事情)。这样的一个将包含真正的基本功能,如 memcpy、基本宏等。C 标准有一种特殊的一致性模式,称为freestanding,它只需要非常有限的功能集,也适用于内核。实际上,我对 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;
}
我们很高兴,它实际上可以编译并运行:)
是的,这是可能的,但是您必须进行系统调用并手动设置您的入口点。
带有入口点的最小程序示例:
.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
在纯 C? 正如其他人所说,您仍然需要一种方法来进行系统调用,因此您可能需要为此下拉到内联 asm。也就是说,如果使用 gcc,请查看 -ffreestanding。
您需要一种方法来防止 C 编译器生成依赖于 libc 的代码,这gcc
可以通过-fno-hosted
. 而且您需要一个汇编语言例程来实现syscall(2)
. 如果你能得到合适的 OS doco,它们并不难写。在那之后,您将参加比赛。
好吧,您需要使用一些系统调用将所有信息加载到内存中,所以我对此表示怀疑。
而且您几乎必须使用 exit(),只是因为 Linux 的工作方式。
是的,你可以,但这很棘手。
基本上没有任何意义。
您可以静态链接程序,但随后 C 库的适当部分包含在其二进制文件中(因此它没有任何依赖项)。
You can completely do without the C library, in which case you need to make system calls using the appropriate low-level interface, which is architecture dependent, and not necessarily int 0x80.
If your goal is making a very small self-contained binary, you might be better off static-linking against something like uclibc.