写底层代码,我们需要特别的手段去调试,去debug.本文针对几种应用场景,介绍几种手段.
1. 查看文件的二进制值 - hexdump命令
以文章(2)中的head程序为例子
ld head.o -m elf_i386 -Ttext 0 -e startup_32 -o system之后,生成system是有文件头的可执行文件,并不是纯粹的代码.
hexdump system
命令输出如下:
0000000 457f 464c 0101 0001 0000 0000 0000 00000000010 0002 0003 0001 0000 0000 0000 0034 00000000020 1140 0000 0000 0000 0034 0020 0001 00280000030 0009 0006 0001 0000 1000 0000 0000 00000000040 0000 0000 0018 0000 0018 0000 0005 00000000050 1000 0000 0000 0000 0000 0000 0000 00000000060 0000 0000 0000 0000 0000 0000 0000 0000*0001000 10b8 0000 8e00 8ed8 8ec0 8ee0 b8e8 00cc0001010 0000 ba66 8000 feeb 001c 0000 0002 00000001020 0000 0004 0000 0000 0000 0000 0018 00000001030 0000 0000 0000 0000 005f 0000 0002 0000...
objcopy -O binary -R .note -R .comment system kernel之后,生成kernel文件是纯的二进制代码
hexdump kernel
命令输出如下:
0000000 10b8 0000 8e00 8ed8 8ec0 8ee0 b8e8 00cc0000010 0000 ba66 8000 feeb 0000018
红色部分对比,发现去掉了很多东西,就剩下了可执行代码,凭什么说是可执行二进制代码呢?看下面的方法.
2. bochs反汇编 - u命令
bochs运行,结果如下:
You can also start bochs with the -q option to skip these menus.1. Restore factory default configuration2. Read options from...3. Edit options4. Save options to...5. Restore the Bochs state from...6. Begin simulation7. Quit nowPlease choose one: [6]
回车继续:
00000000000i[ ] installing x module as the Bochs GUI00000000000i[ ] using log file bochsout.txtNext at t=0(0) [0x00000000fffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b ; ea5be000f0<bochs:1> 输入命令 pb 0x7c00 回车,意思是在0x7c00地址处设置断点
输入命令c,结果如下:
<bochs:1> pb 0x7c00<bochs:2> c(0) Breakpoint 1, 0x00007c00 in ?? ()Next at t=3915811(0) [0x0000000000007c00] 0000:7c00 (unk. ctxt): jmp far 07c0:0005 ; ea0500c007<bochs:3> 程序定在了0000:7c00处,绿色部分是物理地址,蓝色0000:7c00是cs:ip,粉色jmp far 07c0:0005是汇编指令,黑色部分是二进制机器指令
输入命令n,执行下一条指令,一直执行,等到bootloader把head加载到0x1000完成后,结果如下:
(0) [0x0000000000007c2c] 07c0:002c (unk. ctxt): mov dx, 0x0000 ; ba0000<bochs:19> Next at t=3925587(0) [0x0000000000007c2f] 07c0:002f (unk. ctxt): mov cx, 0x0002 ; b90200<bochs:20> Next at t=3925588(0) [0x0000000000007c32] 07c0:0032 (unk. ctxt): mov ax, 0x1000 ; b80010<bochs:21> Next at t=3925589(0) [0x0000000000007c35] 07c0:0035 (unk. ctxt): mov es, ax ; 8ec0<bochs:22> Next at t=3925590(0) [0x0000000000007c37] 07c0:0037 (unk. ctxt): xor bx, bx ; 31db<bochs:23> Next at t=3925591(0) [0x0000000000007c39] 07c0:0039 (unk. ctxt): mov ax, 0x0204 ; b80402<bochs:24> Next at t=3925592(0) [0x0000000000007c3c] 07c0:003c (unk. ctxt): int 0x13 ; cd13<bochs:25> Next at t=3973287(0) [0x0000000000007c3e] 07c0:003e (unk. ctxt): jnb .+10 (0x00007c4a) ; 730a<bochs:26> Next at t=3973288(0) [0x0000000000007c4a] 07c0:004a (unk. ctxt): cli ; fa
输入命令 u 0,结果如下:
<bochs:45> u 0x10000 0x1001000010000: ( ): mov ax, 0x0010 ; b8100000010003: ( ): add byte ptr ds:[bx+si], al ; 000000010005: ( ): mov ds, ax ; 8ed800010007: ( ): mov es, ax ; 8ec000010009: ( ): mov fs, ax ; 8ee00001000b: ( ): mov gs, ax ; 8ee80001000d: ( ): mov ax, 0x00cc ; b8cc00一定恍然大悟了吧,bootloader把head加载到了0x1000:0x0处,u命令把0x1000:0x0处的第一条指令反汇编后,mov ax,0x0010正是head程序的第一条指令.
看后边的b81000和前边hexdump kernel输出结果10b8 0000 8e00比较,实际上是同一个数据,所以确定objcopy后的输出时二进制指令.
2. 查看目标文件的内容 - objdump命令
objdump system或者objdump head
输出如下:system: file format elf32-i386Disassembly of section .text:00000000 <startup_32>: 0: b8 10 00 00 00 mov $0x10,
