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程序
“Hello World”执行的最小指令集和汇编器/编译器
这个是struts2入门示例HelloWorld所需的最小必备包。
VS2015下使用纯WIN32 API写的Hello World!基本上算是C/C++能写到的最小版本。资源包含工程文件、源代码文件及生成的32/64位的EXE文件
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 ...
什么是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 ...
虽然不是很会,也不是很懂,完全仿照世界编程大赛第一名的作品的代码编写方式写了个helloworld,也算是最小的helloworld了
一个简单,最小的Maven示例:hello world 要在此git repo中创建文件,我们已经运行了mvn archetype:generate from mvn archetype:generate -DgroupId=...
Akka-HTTP Hello World Akka-http的最小示例安装并运行$ ##### Tutorial Install/Run #####$ git clone https://github.com/allenhwkim/akka-http-helloworld.git$ cd akka-http-helloworld$ sbt compile run$ curl ...
使用node-api开发node C++插件的cmake-js Hello World 最小化项目. 1.解压 2.进入目录,运行yarn 安装依赖 3.yarn install 4.yarn test CMakeLists.txt: cmake_minimum_required(VERSION 3.12) cmake_policy(SET CMP...
最小的Node.js Hello World示例 此仓库包含一个用Node编写的最小的hello world应用程序。 此仓库将记录您可以部署此应用程序的多种方式。 在本地运行 npm install npm start 在容器中运行 docker build -t node-...
用Myeclipse 做的小例子,通过最小的例子可以深入学习。
什么是Node Helloworld? 这是一个用NodeJS编写的最小的hello world应用程序,用于测试目的。TL; DRDocker撰写$ curl -LO ...
一个简单,最小的Maven示例:hello world 要在此git repo中创建文件,我们已经运行了mvn archetype:generate from mvn archetype:generate -DgroupId=...
SimpleOS 仅显示“ Hello World!”的裸机最低操作系统。 并列出字母。 您可以在虚拟机下运行此操作系统。 qemu就是这样一种VM。 如果希望使用qemu运行(仅在Linux上进行了测试),则使用终端cd进入包含boot.bin文件...
full-stack-hello full-stack-hello是一种最小的虚拟机套件,能够在临时性的“ Hello World”程序执行所依赖的技术堆栈的任何级别上执行任务。 这意味着:指令集Architec full-stack-hello full-stack-hello是最小的...
由于这只是一个单一的来源,你编译它 javac -cp /usr/share/java/eclipselink-jpa-2.1-spec.jar HelloWorld.java并运行它,例如 java -cp .:/usr/share/java/eclipselink.jar:/usr/share/java/eclipselink-jpa-2.1-...
crccheck/hello-world latest 2b28c6ad8d1b 4 months ago 1.2MB 我最初做这个是因为有很多场景我想要一个支持 HTTP 的 Docker 容器,但每个指南都使用需要几秒钟才能下载的图像。 有了一个很小的 Docker 镜像,...
使用Vue.js和Electron构建Hello World桌面应用程序 安装vue cli npm install -g @vue/cli 项目设置 npm install 编译和热重装以进行开发 npm run serve 编译并最小化生产 npm run build 运行测试 npm run test...