欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

最小helloworld 博客分类: OS helloworld嵌套汇编系统调用 

程序员文章站 2024-03-18 15:38:46
...

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

 

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