`
tcspecial
  • 浏览: 899325 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

最小helloworld

    博客分类:
  • OS
阅读更多

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

 

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

  

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics