首页 > 其他分享 >最小helloworld

最小helloworld

时间:2022-12-15 14:35:21浏览次数:37  
标签:00 000000 00000000 dev21 elf 最小 helloworld root


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个字节。

 

 参考资料:《程序员的自我修养》

  

 

标签:00,000000,00000000,dev21,elf,最小,helloworld,root
From: https://blog.51cto.com/u_1923895/5939831

相关文章

  • SSM整合(spring-springmvc-mybatis)之HelloWorld
    一、目录结构  helloworld(SSM)创建步骤:步骤一:创建一个类型为DynamicWebProject 名称为ssm的项目步骤二:加入jar包:spring核心jar包:commons-logging-1.2.jarspring-bean......
  • [JSOI2015]最小表示
    链接:https://www.luogu.com.cn/problem/P6134题目描述:给定一个\(DAG\),求最多删多条边能使任意两点的连通性不会发生改变。题解:手玩几组数据可以发现答案就是图中去掉边\(......
  • 【算法实践】| 一步步手把手带你实现寻找最小公倍数
    前言其实最小公倍数的概念和计算最小公倍数的方法.那是我们在学习小学数学的时候就已经掌握的数学知识,为了更加通俗易懂一点,本文先从一个'分元宝'的故事入手:亡故的先父留......
  • SpringMVC中HelloWorld实现(三)
    我机器的开发环境为:开发工具:EclipseForJavaEE;数据库:MySql5.5.35;运行环境:TomCatV7.0;JDK:JDK1.7.0_45;项目工程为:DynamicWebProject; 一、项目依赖的jar包:[ht......
  • HelloWorld编写与编译
    HelloWorld1.随便新建一个文件夹,存放代码2.新建一个Java文件文件后缀名为.javaHello.java【注意】系统可能没有显示文件后缀名,我们需要手动打开3.编写代码p......
  • python从中文数字数据区间提取minmax最小值、最大值返回pandas
    先上结果:定义转换函数代码:defrange2min(text):if'千'intext:text=text.replace('千','000')#替换中文为数字if'万'intext:text=tex......
  • 博 客 测 试 --> P3366【模板】最小生成树
    P3366【模板】最小生成树题目描述如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz。输入格式第一行包含两个整数N,M,表示该图共有N个结点和M条无向边。......
  • 2190. 有源汇上下界最小流
    2190.有源汇上下界最小流和最大流差不多首先是判断可行吗最后要把起点和终点调换,然后减去#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongcon......
  • 旋转数组的最小数字
    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个升序的数组的一个旋转,输出旋转数组的最小元素。例如数组 {3,4,5,1,2}{3,4,5,1,2} 为 {1,......
  • 力扣---746. 使用最小花费爬楼梯
    给你一个整数数组cost,其中cost[i]是从楼梯第i个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。你可以选择从下标为0或下标为1的......