author:luojiafei
blog: http://blog.csdn.net/luojiafei
e-mail: 1196722167@qq.com
data: 2012/1/30
(注:这里的最小是指我能做到的最小)
最小的hello world
我们刚学编程的时候就是学习写hello world,现在我就讲一下我所写的最小的hello world.
首先一个用c语言写的hello为
#include <stdio.h>
int main() {
printf ("Hi World\n");
return 0;
}
这个chello文件大小为2984字节。这时主要因为用到了printf和gcc为了你增加了其他段,然而这些段在这里作用不大。那这该如何解决呢?汇编!
以下是用nasm语法编写的hello world汇编:
[section .data]
msg: db "Hello World",10 ;10为回车
len: equ $-msg
[section .text]
global _start ;我们必须导出这个入口,让linker知道
_start:
mov edx,len
mov ecx,msg
mov ebx,1
mov eax,4
int 0x80 ;write(1, msg, len),标准输出的fd为1
mov ebx,0
mov eax,1
int 0x80 ;exit()
以及对应的makefile:
all: nasm -f elf hello.asm -o hello.o ld -s hello.o -o hello
运行结果:Hello World
这样生成的elf文件为大约为400字节,一下就比小了很多,主要是因为直接编写系统调用,以及连接时使用-s参数去除符号表等信息来帮文件“瘦身”。
当然如果这样就结束那就太简单了,我们接下来要直接修改文件的机械码。在Linux下有很多关于二进制编辑器,这里我使用ghex.
输入命令ghex2 hello 后便得到其机械码:
下面我们把Hello world后面的内容删除掉,而这样做文件也能正常运行(PS:因为后面都是作用不大的段):
这样文件大小变为176字节,(啊,这已经挺理想了)。但我们可以看到在第一行里有9个内容全部为0的字节,好像被白白浪费了?没错,这些的确是elf的保留字段,也就是目前没有到的字段。但我们的”Hello World\n"这里有12个字节,那怎么办?从一切从实际出发的角度来看,我觉得用一个耍赖的方法,把"Hello World\n"变成"Hi World\n".
下面,我们把最后面的9个字节放到第一行那9个没用的字节里(起始地址为0x07),再把0x86中的A4改为07,再把0xA2开始的两个字节删除(PS:这两字节为了地址对齐,没有实质作用)。最后变成下面这样:
最后为162字节。运行结果:Hi World
其实这里还可以还可以再精简一些,但估计不会减小太多字节,并且用a.out格式的话,字节数应该会更小。望高手指点!