hello world程序是学每种编程语言的启蒙程序,所谓麻雀虽小,五脏俱全。最近看《程序员的自我修养》最小helloworld程序章节,觉得甚是精彩,特此整理下。
一. 入门级helloworld
[root@dev21 elf]# ll tinyhello -rwxr-xr-x 1 root root 4719 Dec 9 14:31 tinyhello [root@dev21 elf]# readelf -h tinyhello ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Number of program headers: 7 Size of section headers: 40 (bytes) Number of section headers: 28 Section header string table index: 25
上述代码调用printf()函数打印字符串,程序调用了glib库,编译文件大小为4.7k。glibc库太庞大,编译出的程序包含很多段,有28个段。
二. 汇编优化
char *str = "Hello world!\n"; /** * 调用中断服务write(),eax传递中断号4,ebx,ecx,edx传递参数 * 中断服务表见:linux-3.18.6/arch/x86/syscalls/syscall_32.tbl */ void print() { asm( "movl $13,%%edx \n\t" "movl %0,%%ecx \n\t" "movl $0,%%ebx \n\t" "movl $4,%%eax \n\t" "int $0x80 \n\t" ::"r"(str):"edx","ecx","ebx" ); } // 中断调用exit() void exit() { asm( "movl $42,%ebx \n\t" "movl $1,%eax \n\t" "int $0x80 \n\t" ); } // 系统入口 void nomain() { print(); exit(); }
由于没有使用main函数,无法直接编译,需手动指定函数入口nomain。
gcc -c -fno-builtin tinyhello.c ld -static -e nomain -o tinyhello tinyhello.c
[root@dev21 elf]# ll tinyhello1 -rwxr-xr-x 1 root root 1031 Dec 9 16:01 tinyhello1 [root@dev21 elf]# readelf -h tinyhello1 ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Number of program headers: 3 Size of section headers: 40 (bytes) Number of section headers: 9 Section header string table index: 6 [root@dev21 elf]# readelf -S tinyhello1 There are 9 section headers, starting at offset 0x154: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 08048094 000094 00003f 00 AX 0 0 4 [ 2] .rodata PROGBITS 080480d3 0000d3 00000e 00 A 0 0 1 [ 3] .data PROGBITS 080490e4 0000e4 000004 00 WA 0 0 4 [ 4] .bss NOBITS 080490e8 0000e8 000000 00 WA 0 0 4 [ 5] .comment PROGBITS 00000000 0000e8 00002e 00 0 0 1 [ 6] .shstrtab STRTAB 00000000 000116 00003d 00 0 0 1 [ 7] .symtab SYMTAB 00000000 0002bc 000110 10 8 10 4 [ 8] .strtab STRTAB 00000000 0003cc 00003b 00 0 0 1
C语言嵌套汇编版本的hello world才1k左右,含9个段。
三. 合并程序段
程序2中存在.text,.rodata,.data三个段,可以整合到一个段中,通过链接脚本实现。
ENTRY(nomain) SECTIONS { . = 0x08048000 + SIZEOF_HEADERS; tinytext : {*(.text) *(.data) *(.rodata) } /DISCARD/ : { *(.comment) } }
[root@dev21 elf]# gcc -c -fno-builtin tinyhello.c [root@dev21 elf]# ld -static -T tinyhello.lds -o tinyhello2 tinyhello.o [root@dev21 elf]# ll tinyhello2 -rwxr-xr-x 1 root root 795 Dec 9 16:34 tinyhello2 [root@dev21 elf]# readelf -S tinyhello2 There are 7 section headers, starting at offset 0x120: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] tinytext PROGBITS 08048094 000094 000052 00 WAX 0 0 4 [ 2] .bss NOBITS 080480e8 0000e6 000000 00 WA 0 0 4 [ 3] .note.GNU-stack PROGBITS 00000000 0000e6 000000 00 0 0 1 [ 4] .shstrtab STRTAB 00000000 0000e6 000039 00 0 0 1 [ 5] .symtab SYMTAB 00000000 000238 0000c0 10 6 8 4 [ 6] .strtab STRTAB 00000000 0002f8 000023 00 0 0 1
编译后的程序只有795B,减少了300多字节。
四. 移除符号表
程序3含有.symtab,.strtab两个段,可以通过strip命令移除。
[root@dev21 elf]# strip tinyhello3 [root@dev21 elf]# ll tinyhello3 -rwxr-xr-x 1 root root 472 Dec 9 16:39 tinyhello3 [root@dev21 elf]# readelf -S tinyhello3 There are 5 section headers, starting at offset 0x110: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] tinytext PROGBITS 08048094 000094 000052 00 WAX 0 0 4 [ 2] .bss NOBITS 080480e8 0000e6 000000 00 WA 0 0 4 [ 3] .note.GNU-stack PROGBITS 00000000 0000e6 000000 00 0 0 1 [ 4] .shstrtab STRTAB 00000000 0000e6 000029 00 0 0 1
最终程序只有472个字节。
参考资料:《程序员的自我修养》
相关推荐
"最小的C语言Hello, world程序"是每个初学者接触C语言时的第一个示例,它展示了如何用最少的代码实现一个简单的输出功能。 这个最小的C语言程序通常只包含以下几行代码: ```c #include int main() { printf(...
这里我们将深入探讨"Hello World"程序在C++中的最小指令集、汇编器和编译器的工作原理。 1. **最小指令集**: 指令集是指计算机硬件系统中处理器能理解和执行的基本操作命令。在"Hello World"程序的执行过程中,...
【标题】"mybatis的Helloworld" 在Java开发领域,MyBatis是一个广泛使用的持久层框架,它简化了数据库操作,使开发者能够更方便地进行数据存取。本篇文章将详细解析MyBatis的“Hello World”实例,帮助初学者快速...
### C语言蛋疼的Hello World代码 #### 标题解析 标题中提到的“蛋疼的Hello World代码”暗示了这是一段非常规且复杂的实现方式,通常用于学习C语言中的指针、内存操作等高级概念。 #### 描述解析 描述部分展示了一...
在Android开发领域,"Hello, World!"项目是一个经典的起点,它为初学者提供了一个简单而直接的编程体验,帮助他们理解和熟悉Android应用的基本构建过程。本文将深入探讨这个入门实例,带您逐步走进Android开发的世界...
在移动开发领域,"HelloWorld" demo 是一个非常基础且重要的起点,尤其对于初次接触Android平台的开发者来说。这个简单的程序通常包含一个显示 "Hello, World!" 文本的界面,它是学习新编程语言或框架的第一步,因为...
docker run --rm --name hello cogsmith/helloworld-nodejs # HELLOWORLD: 695144B4BC64 @ 2021-02-18T01:19:03.199Z 本地Web服务器@端口99 docker run -d --rm --name hellolocal --env PORT=9 -p 127.0.0.1:99:9 ...
本课程的核心是通过“Hello World”实例来引导初学者理解Vue的基本概念和设计思想。 首先,让我们从“Hello World”程序开始。这是每个开发者学习新语言或框架时的入门步骤。在Vue中,创建“Hello World”程序非常...
标题 "Hello world -- OS" 暗示我们正在探讨的是操作系统开发的基础教程,通常这个简单的程序是编程初学者进入系统编程领域的第一步。在这个场景中,"Hello world" 不再是简单的用户界面输出,而是可能涉及操作系统...
这个"struts2 HelloWorld最小必备包"是初学者入门Struts2框架的起点,它包含了运行一个简单的"Hello, World!"示例所需的所有核心组件。 1. **Struts2 Core** (`struts2-core-2.5.2.jar`): 这是Struts2框架的核心...
在本文中,我们将深入探讨如何在Visual Studio 2015环境下使用纯Windows API编写一个基本的"Hello, World!"程序。Windows API是Microsoft提供的一组函数和结构,用于开发Windows操作系统上的应用程序。这个API提供了...
标题 "asm.zip_asm hello world_world" 和描述 "asm hello world test" 暗示了这个压缩包的内容与汇编语言编程有关,特别是涉及到一个简单的 "hello world" 程序的创建和测试。汇编语言是计算机编程的一种底层语言,...
"helloWorld"这个文件可能是这个工作流示例的源代码或者配置文件。在许多工作流引擎中,如Activiti、Nintex、BPMN(Business Process Model and Notation)等,开发者通常会创建一个简单的“Hello World”流程来展示...
【Jbpm4HelloWorld】是基于JBPM(Java Business Process Management)框架的入门示例,这个项目旨在帮助初学者快速理解并掌握JBPM的基本用法。JBPM是一个开源的工作流管理系统,它允许开发者设计、执行和管理业务...
在创建新项目的过程中,你需要设置项目的基本信息,如项目名称(可以是"HelloWorld")、包名(通常以反向域名的形式表示,如com.example.helloworld)、最小SDK版本(决定应用支持的Android系统版本)等。...
什么是Node Helloworld? 这是一个用NodeJS编写的最小的hello world应用程序,用于测试目的。 TL; DR Docker撰写 $ curl -LO ...
这是部署由AWS Lambda函数支持的HTTP API的最小Hello World示例。 该功能用Go编写,并且使用Terraform自动化部署。 先决条件 Terraform and Go 安装和 。 在具有Homebrew的macOS上: $ brew install go terraform ...
标题 "air for android hello world" 暗示我们即将探讨的是使用Adobe AIR技术在Android平台上构建一个基础的“Hello World”应用。Adobe AIR(Adobe Integrated Runtime)允许开发者使用Flash、Flex或HTML5来创建跨...
一个简单,最小的Maven示例:hello world 要在此git repo中创建文件,我们已经运行了mvn archetype:generate from mvn archetype:generate -DgroupId=...