目标驱动型,是人的性格的一种描述,它的核心是目标,先有目标然后驱使人们做出行动。
下面我就以 a.out 为例,研究一个 C 语言编译链接的问题,同时感受一下目标驱动型学习方法的魅力。
大概介绍下思路
总之,这是一种倒着的学习路线,目标倒逼原理。
话不多说,开搞!
7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 02 00 3e 00 01 00 00 00 78 00 40 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 38 00 01 00 00 00 00 00 00 00 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 a9 00 00 00 00 00 00 00 a9 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 b8 01 00 00 00 bf 01 00 00 00 48 be 9d 00 40 00 00 00 00 00 ba 0d 00 00 00 0f 05 b8 3c 00 00 00 48 31 ff 0f 05 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a
这就是 a.out 的 16 进制全部内容了,总共 169 字节,我们把以上内容存到 a.out 中,看看能不能运行。
我使用的环境是 ubuntu,我们需要一个可以方便编辑 16 进制文件的软件,这里我使用的是 bless
安装命令
sudo apt install bless
我们把上面的 16 进制内容复制到 bless 编辑器中。(可能是 markdown 格式的问题,直接从博文中拷贝粘贴,可能会出现被 bless 识别成字符的形式,其实我们这里是 16 进制形式。因此建议先将内容拷贝到 Notepad++ 中,去掉最后面的换行,再粘贴到 bless 中。)
另存为 a.out
增加可执行权限
$ chmod +x a.out
运行
$ ./a.out
hello world
👏👏👏 太神奇了,可以运行哎!到底什么原理呢?
前 64 字节为 ELF 头,接着是 56 字节的程序头,再接着是 37 字节的代码,最后是 12 字节的字符串数据 “hello world”。
# ELF Header
00: 7f 45 4c 46 02 01 01 00 # e_ident
08: 00 00 00 00 00 00 00 00 # reserved
10: 02 00 # e_type
12: 3e 00 # e_machine
14: 01 00 00 00 # e_version
18: 78 00 40 00 00 00 00 00 # e_entry
20: 40 00 00 00 00 00 00 00 # e_phoff
28: 00 00 00 00 00 00 00 00 # e_shoff
30: 00 00 00 00 # e_flags
34: 40 00 # e_ehsize
36: 38 00 # e_phentsize
38: 01 00 # e_phnum
3a: 00 00 # e_shentsize
3c: 00 00 # e_shnum
3e: 00 00 # e_shstrndx
# Program Header
40: 01 00 00 00 # p_type
44: 05 00 00 00 # p_flags
48: 00 00 00 00 00 00 00 00 # p_offset
50: 00 00 40 00 00 00 00 00 # p_vaddr
58: 00 00 40 00 00 00 00 00 # p_paddr
60: aa 00 00 00 00 00 00 00 # p_filesz
68: aa 00 00 00 00 00 00 00 # p_memsz
70: 00 10 00 00 00 00 00 00 # p_align
# Code
78: b8 01 00 00 00 # mov $0x1,%eax
7d: bf 01 00 00 00 # mov $0x1,%edi
82: 48 be 9d 00 40 00 00 00 00 00 # movabs $0x40009d,%rsi
8c: ba 0d 00 00 00 # mov $0xd,%edx
91: 0f 05 # syscall
93: b8 3c 00 00 00 # mov $0x3c,%eax
98: 48 31 ff # xor %rdi,%rdi
9b: 0f 05 # syscall
9d: 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a # "hello world\n"
到这里,我们已然已经看清了一个二进制可执行文件(ELF)里面到底都有什么内容,这就是纯手工打造 a.out 带来的好处,接下来,留给我们继续探索的内容还有:
看吧,从一个小目标出发,我们也能够顺藤摸瓜式地学到整个路线中的众多内容,如果不是被这个小目标驱使着,如果是自上而下地研究的话,可能搞着搞着就放弃了,这就是自下而上学习的魅力,目标倒逼原理。