c语言是否可以不要main函数,HelloWorld... 不用C语言库,不用main函数

1.从程序员的自我修养上摘录的。

2.这不是卖弄技巧,这是深入了解链接和编译。

开始

使用c语言输出hello world,不用C语言库,不用main函数。怎么做?

1. 我们需要printf这样的功能。

2. 一段程序需要一个程序入口,C语言默认是main。

有这样的武器:

1. GCC支持内嵌汇编。

2. 使用汇编直接产生中断,可以使用系统调用。

3. ld连接器可以指定程序入口。

好了,我们要做的就是,在程序中使用GCC内嵌汇编,产生中断,进行write的系统调用, 在链接程序时,指定自己的程序入口。代码如下:

/*

* @FileName: TinyHelloWorld.c

* @Author: wzj

* @Brief:

*

*

*

*

*

* @History:

*

*

*

* @Date: 2012年06月19日星期二22:46:23

*

*/

char* str = "Hello world\n";

void

print()

{//使用write的系统调用, write的调用号为4,原型为int write(int filedesc, char* buffer, int size)

//这里的系统调用,先将参数写入寄存器,之后传入write调用

asm(

"movl $13, %%edx \n\t"//str的长度

"movl %0, %%ecx \n\t" //缓冲区,这里的%0,指的是“r”后面的字符串地址,也就是传入到这段汇编的参数。

"movl $0, %%ebx \n\t"//打印到标准输出, 也就是0

"movl $4, %%eax\n\t"//将系统调用号传入eax。

"int $0x80\n\t"//执行中断, 调用write函数

::"r" (str):"edx","ecx", "ebx"//传入的参数列表, 被重命名的寄存器列表。

);

}

void

exit()

{

asm(

"movl $42,%ebx \n\t "

"movl $1, %eax \n\t"

"int $0x80\n\t"

);

}

//这里是程序的入口

void

nomain()

{

print();

exit();

}

进行编译:

gcc -c -fno-builtin  TinyHelloWorld.c

ld -static -e nomain -o TinyHelloWorld TinyHelloWorld.o

注:-fno-buildtin  说明禁止使用gcc的内置函数, -static指明使用静态链接进行链接。 -e nomain 指定函数入口为 nomain。

或者,我们可以使用一份链接脚本:

ENTRY(nomain) :指定程序入口

SECTIONS

{

. = 0x08048000 + SIZEOF_HEADERS; ;指明程序开始的地址。

tinytext : { *(.text) *(.data) *(.rodata) } ;将后面三段,合成当前一段。

/DISCARD/: { *(.comment) }

}

进行编译:

gcc -c -fno-builtin  TinyHelloWorld.c

ld -static -T TinyHelloWorld.ld  -o TinyHelloWorld TinyHelloWorld.o

注:使用这份脚本编译之后,与前面的不同之处是,.text  .data  .rodata 被合并成了.tinytext。    使用objdump -h 可以看到两者最终生成文件的不同之处。