HelloWorld... 不用C语言库,不用main函数

本文详细介绍了如何使用GCC内嵌汇编、系统调用和链接器特性,仅通过C语言语法实现输出'Helloworld',不依赖于main函数或C语言库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 可以看到两者最终生成文件的不同之处。


### 回答1: 可以使用以下C语言代码来输出"Hello world": ```c #include <stdio.h> int main() { printf("Hello world\n"); return 0; } ``` 在这个程序中,我们使用了标准库头文件<stdio.h>中的printf函数来输出字符串"Hello world"。这个字符串必须被包含在引号中,并以一个换行符"\n"结尾,以便在输出后开始一个新行。最后,main函数以0为返回值结束,这表示程序已成功执行。 ### 回答2: 使用C语言输出"Hello, world!"的一种常见的方法是使用printf函数。printf函数是C语言中的一个标准库函数,用于打印输出文本。 代码示例: ```c #include <stdio.h> int main() { printf("Hello, world!\n"); return 0; } ``` 这段代码首先包含了<stdio.h>头文件,该头文件中包含了printf函数的声明。然后,定义了一个main函数,它是程序的入口点。 在main函数中,调用了printf函数,该函数会将字符串"Hello, world!\n"打印到标准输出设备(通常是控制台)。其中,\n表示换行符,使输出结果换行显示。 最后,main函数返回0,表示程序正常结束。整个代码的运行结果就是在输出设备上显示"Hello, world!"。 ### 回答3: 在C语言中,要输出"Hello world",我们可以使用标准库函数printf。下面是一个简单的C语言程序来实现输出"Hello world": ```c #include <stdio.h> int main() { printf("Hello world.\n"); return 0; } ``` 在这个程序中,我们包含了标准头文件stdio.h,该头文件中包含了printf函数的声明。然后,我们定义了一个名为main函数作为程序的入口点。在main函数中,我们使用printf函数来输出"Hello world.\n",其中\n表示换行。最后,我们使用return语句来结束程序的执行,并返回0作为程序的退出状态码。 要编译并运行这个C程序,你可以使用任何C语言编译器。将上述代码保存为一个扩展名为.c的文件(比如hello.c),然后在命令行中使用以下命令来编译和运行程序: ``` gcc hello.c -o hello ./hello ``` 这将使用gcc编译器将hello.c文件编译为一个可执行文件hello,然后通过./hello命令来运行这个可执行文件。你会看到"Hello world."在终端上输出。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值