-
-
[旧帖] [翻译]42字节可执行文件;ELF介绍;求Kx(三) 0.00雪花
-
发表于: 2012-9-23 11:50 1108
-
可执行文件进一步缩减的方法是使用更短的指令。
汇编代码和机器码的对应如下:
00000000 B801000000 mov eax, 1
00000005 BB2A000000 mov ebx, 42
0000000A CD80 int 0x80
观察得出,寄存器ebx不必全部初始化,因为OS只使用最低的字节,那么只用bl可以,从而仅使用2个字节,而不是5个。
同时,还可以先对eax进行异或,再加1,再省2个字节。
00000000 31C0 xor eax, eax
00000002 40 inc eax
00000003 B32A mov bl, 42
00000005 CD80 int 0x80
另外,不使用GCC进行链接,直接调用链接器ld.
$ nasm -f elf tiny.asm
$ ld -s tiny.o
$ ./a.out ; echo $?
42
$ wc -c a.out
368 a.out
虽然省了5个字节,但是对齐多用了一个,所以与上次相比,只节省了4个字节。
程序本身仅有7个字节,但是可执行文件长度为何会多出来361个字节呢?文件里到底多了哪些内容?我们使用objdump来看一看。
$ objdump -x a.out | less
我们来看下面的部分:
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000007 08048080 08048080 00000080 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .comment 0000001c 00000000 00000000 00000087 2**0
CONTENTS, READONLY
.text段显示确实只有7个字节;但是comment是什么?而且它占据了28个字节!指示的位置是00000087(十六进制),如果使用十六进制的查看工具可以看到内容如下:
00000080: 31C0 40B3 2ACD 8000 5468 6520 4E65 7477 1.@.*...The Netw
00000090: 6964 6520 4173 7365 6D62 6C65 7220 302E ide Assembler 0.
000000A0: 3938 0000 2E73 796D 7461 6200 2E73 7472 98...symtab..str
nasm在编译的时候添加了这么多信息!那么我们使用gas,AT&T来试一下:
;tiny.s
.globl _start
.text
_start:
xorl %eax, %eax
incl %eax
movb $42, %bl
int $ox80
然后使用gcc进行编译:
$ gcc -s -nostdlib tiny.s
$ ./a.out ; echo $?
42
$ wc -c a.out
368 a.out
大小上并没有变化!使用objdump查看,发现虽然没有了comment,但是多了两个无用的单元:
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000007 08048074 08048074 00000074 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 0804907c 0804907c 0000007c 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 0804907c 0804907c 0000007c 2**2
ALLOC
data和bss这两部分虽然长度为0,但是仍然占了位置;那么如何去除这些无用的部分呢?
为了解决这个问题,我们必须要了解ELF的格式。
汇编代码和机器码的对应如下:
00000000 B801000000 mov eax, 1
00000005 BB2A000000 mov ebx, 42
0000000A CD80 int 0x80
观察得出,寄存器ebx不必全部初始化,因为OS只使用最低的字节,那么只用bl可以,从而仅使用2个字节,而不是5个。
同时,还可以先对eax进行异或,再加1,再省2个字节。
00000000 31C0 xor eax, eax
00000002 40 inc eax
00000003 B32A mov bl, 42
00000005 CD80 int 0x80
另外,不使用GCC进行链接,直接调用链接器ld.
$ nasm -f elf tiny.asm
$ ld -s tiny.o
$ ./a.out ; echo $?
42
$ wc -c a.out
368 a.out
虽然省了5个字节,但是对齐多用了一个,所以与上次相比,只节省了4个字节。
程序本身仅有7个字节,但是可执行文件长度为何会多出来361个字节呢?文件里到底多了哪些内容?我们使用objdump来看一看。
$ objdump -x a.out | less
我们来看下面的部分:
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000007 08048080 08048080 00000080 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .comment 0000001c 00000000 00000000 00000087 2**0
CONTENTS, READONLY
.text段显示确实只有7个字节;但是comment是什么?而且它占据了28个字节!指示的位置是00000087(十六进制),如果使用十六进制的查看工具可以看到内容如下:
00000080: 31C0 40B3 2ACD 8000 5468 6520 4E65 7477 1.@.*...The Netw
00000090: 6964 6520 4173 7365 6D62 6C65 7220 302E ide Assembler 0.
000000A0: 3938 0000 2E73 796D 7461 6200 2E73 7472 98...symtab..str
nasm在编译的时候添加了这么多信息!那么我们使用gas,AT&T来试一下:
;tiny.s
.globl _start
.text
_start:
xorl %eax, %eax
incl %eax
movb $42, %bl
int $ox80
然后使用gcc进行编译:
$ gcc -s -nostdlib tiny.s
$ ./a.out ; echo $?
42
$ wc -c a.out
368 a.out
大小上并没有变化!使用objdump查看,发现虽然没有了comment,但是多了两个无用的单元:
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000007 08048074 08048074 00000074 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 0804907c 0804907c 0000007c 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 0804907c 0804907c 0000007c 2**2
ALLOC
data和bss这两部分虽然长度为0,但是仍然占了位置;那么如何去除这些无用的部分呢?
为了解决这个问题,我们必须要了解ELF的格式。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: