Saturday, October 1, 2011

Dissecting a bootloader

I am sick of bootloaders being mysterious and inaccessible, so I have decided to take a closer look at mine.



I'm running Ubuntu on an x86.

man boot
...In most systems, this primary loader is very limited due to various constraints. Even on non-PC systems there are some limitations to the size and complexity of this loader, but the size limitation of the PC MBR (512 bytes including the partition table) makes it almost impossible to squeeze a full OS Loader into it. ...

So we want the first half kilobyte of the main hard drive. To figure out the disk being used, mount should typcially do the trick:

mount
/dev/sda5 on / type ext4 (rw,errors=remount-ro,commit=600)

So I'm using /dev/sda.

Well use the low level data transfer tool dd. (Really can't we get rid of these useless historical tool names?) Since hard drive blocks are 512 bytes, we'll want the first one.
craigp@lamina> sudo dd if=/dev/sda count=1 > mbr.o
[sudo] password for craigp:
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000207665 s, 2.5 MB/s
craigp@lamina> file mbr.o
mbr.o: x86 boot sector; partition 1: ID=0x7, active, starthead 32, startsector 2048, 407552 sectors; partition 2: ID=0x7, starthead 126, startsector 409600, 310984704 sectors; partition 3: ID=0x5, starthead 254, startsector 311396350, 313745410 sectors, code offset 0x63
Yes it's the correct size and contains the expected information! So let's see what it's up to.

craigp@lamina> objdump -D -b binary -mi386 -Maddr16,data16 mbr.o
00000000 <.data>:
0: eb 63 jmp 0x65
2: 90 nop
3: d0 bc 00 7c sarb 0x7c00(%si)
7: fb sti
8: 8e c0 mov %ax,%es
a: 8e d8 mov %ax,%ds
c: 8b f4 mov %sp,%si
e: bf 00 06 mov $0x600,%di
11: b9 00 02 mov $0x200,%cx
14: fc cld
15: f3 a4 rep movsb %ds:(%si),%es:(%di)
17: ea 60 06 00 00 ljmp $0x0,$0x660
1c: 00 00 add %al,(%bx,%si)
1e: 00 00 add %al,(%bx,%si)
20: 52 push %dx
21: 65 63 6f 76 arpl %bp,%gs:0x76(%bx)
25: 65 gs
26: 72 79 jb 0xa1
28: 4d dec %bp
29: 67 72 20 addr32 jb 0x4c
2c: 00 98 d9 22 add %bl,0x22d9(%bx,%si)
...
4c: 00 00 add %al,(%bx,%si)
4e: 0d 0a 00 or $0xa,%ax
51: 00 00 add %al,(%bx,%si)
53: 00 57 00 add %dl,0x0(%bx)
56: 00 00 add %al,(%bx,%si)
58: ff (bad)
59: ff 00 incw (%bx,%si)
5b: 80 01 00 addb $0x0,(%bx,%di)
5e: 00 00 add %al,(%bx,%si)
60: 00 00 add %al,(%bx,%si)
62: 00 00 add %al,(%bx,%si)
64: ff (bad)
65: fa cli
66: 90 nop
67: 90 nop
68: f6 c2 80 test $0x80,%dl
6b: 74 05 je 0x72
6d: f6 c2 70 test $0x70,%dl
70: 74 02 je 0x74
72: b2 80 mov $0x80,%dl
74: ea 79 7c 00 00 ljmp $0x0,$0x7c79
79: 31 c0 xor %ax,%ax
7b: 8e d8 mov %ax,%ds
7d: 8e d0 mov %ax,%ss
7f: bc 00 20 mov $0x2000,%sp
82: fb sti
83: a0 64 7c mov 0x7c64,%al
86: 3c ff cmp $0xff,%al
88: 74 02 je 0x8c
8a: 88 c2 mov %al,%dl
8c: 52 push %dx
8d: bb 17 04 mov $0x417,%bx
90: 80 27 03 andb $0x3,(%bx)
93: 74 06 je 0x9b
95: be 88 7d mov $0x7d88,%si
98: e8 17 01 call 0x1b2
9b: be 05 7c mov $0x7c05,%si
9e: b4 41 mov $0x41,%ah
a0: bb aa 55 mov $0x55aa,%bx
a3: cd 13 int $0x13
a5: 5a pop %dx
a6: 52 push %dx
a7: 72 3d jb 0xe6
a9: 81 fb 55 aa cmp $0xaa55,%bx
ad: 75 37 jne 0xe6
af: 83 e1 01 and $0x1,%cx
b2: 74 32 je 0xe6
b4: 31 c0 xor %ax,%ax
b6: 89 44 04 mov %ax,0x4(%si)
b9: 40 inc %ax
ba: 88 44 ff mov %al,-0x1(%si)
bd: 89 44 02 mov %ax,0x2(%si)
c0: c7 04 10 00 movw $0x10,(%si)
c4: 66 8b 1e 5c 7c mov 0x7c5c,%ebx
c9: 66 89 5c 08 mov %ebx,0x8(%si)
cd: 66 8b 1e 60 7c mov 0x7c60,%ebx
d2: 66 89 5c 0c mov %ebx,0xc(%si)
d6: c7 44 06 00 70 movw $0x7000,0x6(%si)
db: b4 42 mov $0x42,%ah
dd: cd 13 int $0x13
df: 72 05 jb 0xe6
e1: bb 00 70 mov $0x7000,%bx
e4: eb 76 jmp 0x15c
e6: b4 08 mov $0x8,%ah
e8: cd 13 int $0x13
ea: 73 0d jae 0xf9
ec: f6 c2 80 test $0x80,%dl
ef: 0f 84 d0 00 je 0x1c3
f3: be 93 7d mov $0x7d93,%si
f6: e9 82 00 jmp 0x17b
f9: 66 0f b6 c6 movzbl %dh,%eax
fd: 88 64 ff mov %ah,-0x1(%si)
100: 40 inc %ax
101: 66 89 44 04 mov %eax,0x4(%si)
105: 0f b6 d1 movzbw %cl,%dx
108: c1 e2 02 shl $0x2,%dx
10b: 88 e8 mov %ch,%al
10d: 88 f4 mov %dh,%ah
10f: 40 inc %ax
110: 89 44 08 mov %ax,0x8(%si)
113: 0f b6 c2 movzbw %dl,%ax
116: c0 e8 02 shr $0x2,%al
119: 66 89 04 mov %eax,(%si)
11c: 66 a1 60 7c mov 0x7c60,%eax
120: 66 09 c0 or %eax,%eax
123: 75 4e jne 0x173
125: 66 a1 5c 7c mov 0x7c5c,%eax
129: 66 31 d2 xor %edx,%edx
12c: 66 f7 34 divl (%si)
12f: 88 d1 mov %dl,%cl
131: 31 d2 xor %dx,%dx
133: 66 f7 74 04 divl 0x4(%si)
137: 3b 44 08 cmp 0x8(%si),%ax
13a: 7d 37 jge 0x173
13c: fe c1 inc %cl
13e: 88 c5 mov %al,%ch
140: 30 c0 xor %al,%al
142: c1 e8 02 shr $0x2,%ax
145: 08 c1 or %al,%cl
147: 88 d0 mov %dl,%al
149: 5a pop %dx
14a: 88 c6 mov %al,%dh
14c: bb 00 70 mov $0x7000,%bx
14f: 8e c3 mov %bx,%es
151: 31 db xor %bx,%bx
153: b8 01 02 mov $0x201,%ax
156: cd 13 int $0x13
158: 72 1e jb 0x178
15a: 8c c3 mov %es,%bx
15c: 60 pusha
15d: 1e push %ds
15e: b9 00 01 mov $0x100,%cx
161: 8e db mov %bx,%ds
163: 31 f6 xor %si,%si
165: bf 00 80 mov $0x8000,%di
168: 8e c6 mov %si,%es
16a: fc cld
16b: f3 a5 rep movsw %ds:(%si),%es:(%di)
16d: 1f pop %ds
16e: 61 popa
16f: ff 26 5a 7c jmp *0x7c5a
173: be 8e 7d mov $0x7d8e,%si
176: eb 03 jmp 0x17b
178: be 9d 7d mov $0x7d9d,%si
17b: e8 34 00 call 0x1b2
17e: be a2 7d mov $0x7da2,%si
181: e8 2e 00 call 0x1b2
184: cd 18 int $0x18
186: eb fe jmp 0x186
188: 47 inc %di
189: 52 push %dx
18a: 55 push %bp
18b: 42 inc %dx
18c: 20 00 and %al,(%bx,%si)
18e: 47 inc %di
18f: 65 6f outsw %gs:(%si),(%dx)
191: 6d insw (%dx),%es:(%di)
192: 00 48 61 add %cl,0x61(%bx,%si)
195: 72 64 jb 0x1fb
197: 20 44 69 and %al,0x69(%si)
19a: 73 6b jae 0x207
19c: 00 52 65 add %dl,0x65(%bp,%si)
19f: 61 popa
1a0: 64 00 20 add %ah,%fs:(%bx,%si)
1a3: 45 inc %bp
1a4: 72 72 jb 0x218
1a6: 6f outsw %ds:(%si),(%dx)
1a7: 72 0d jb 0x1b6
1a9: 0a 00 or (%bx,%si),%al
1ab: bb 01 00 mov $0x1,%bx
1ae: b4 0e mov $0xe,%ah
1b0: cd 10 int $0x10
1b2: ac lods %ds:(%si),%al
1b3: 3c 00 cmp $0x0,%al
1b5: 75 f4 jne 0x1ab
1b7: c3 ret
1b8: 91 xchg %ax,%cx
1b9: b5 c0 mov $0xc0,%ch
1bb: 25 00 00 and $0x0,%ax
1be: 80 20 21 andb $0x21,(%bx,%si)
1c1: 00 07 add %al,(%bx)
1c3: 7e 25 jle 0x1ea
1c5: 19 00 sbb %ax,(%bx,%si)
1c7: 08 00 or %al,(%bx,%si)
1c9: 00 00 add %al,(%bx,%si)
1cb: 38 06 00 00 cmp %al,0x0
1cf: 7e 26 jle 0x1f7
1d1: 19 07 sbb %ax,(%bx)
1d3: fe (bad)
1d4: ff (bad)
1d5: ff 00 incw (%bx,%si)
1d7: 40 inc %ax
1d8: 06 push %es
1d9: 00 00 add %al,(%bx,%si)
1db: 40 inc %ax
1dc: 89 12 mov %dx,(%bp,%si)
1de: 00 fe add %bh,%dh
1e0: ff (bad)
1e1: ff 05 incw (%di)
1e3: fe (bad)
1e4: ff (bad)
1e5: ff (bad)
1e6: fe 87 8f 12 incb 0x128f(%bx)
1ea: 02 60 b3 add -0x4d(%bx,%si),%ah
1ed: 12 00 adc (%bx,%si),%al
...
1fb: 00 00 add %al,(%bx,%si)
1fd: 00 55 aa add %dl,-0x56(%di)
We should also look at the ascii interpretation:

craigp@lamina> hexdump -C mbr.o
00000000 eb 63 90 d0 bc 00 7c fb 8e c0 8e d8 8b f4 bf 00 |.c....|.........|
00000010 06 b9 00 02 fc f3 a4 ea 60 06 00 00 00 00 00 00 |........`.......|
00000020 52 65 63 6f 76 65 72 79 4d 67 72 20 00 98 d9 22 |RecoveryMgr ..."|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0d 0a |................|
00000050 00 00 00 00 57 00 00 00 ff ff 00 80 01 00 00 00 |....W...........|
00000060 00 00 00 00 ff fa 90 90 f6 c2 80 74 05 f6 c2 70 |...........t...p|
00000070 74 02 b2 80 ea 79 7c 00 00 31 c0 8e d8 8e d0 bc |t....y|..1......|
00000080 00 20 fb a0 64 7c 3c ff 74 02 88 c2 52 bb 17 04 |. ..d|<.t...R...|
00000090 80 27 03 74 06 be 88 7d e8 17 01 be 05 7c b4 41 |.'.t...}.....|.A|
000000a0 bb aa 55 cd 13 5a 52 72 3d 81 fb 55 aa 75 37 83 |..U..ZRr=..U.u7.|
000000b0 e1 01 74 32 31 c0 89 44 04 40 88 44 ff 89 44 02 |..t21..D.@.D..D.|
000000c0 c7 04 10 00 66 8b 1e 5c 7c 66 89 5c 08 66 8b 1e |....f..\|f.\.f..|
000000d0 60 7c 66 89 5c 0c c7 44 06 00 70 b4 42 cd 13 72 |`|f.\..D..p.B..r|
000000e0 05 bb 00 70 eb 76 b4 08 cd 13 73 0d f6 c2 80 0f |...p.v....s.....|
000000f0 84 d0 00 be 93 7d e9 82 00 66 0f b6 c6 88 64 ff |.....}...f....d.|
00000100 40 66 89 44 04 0f b6 d1 c1 e2 02 88 e8 88 f4 40 |@f.D...........@|
00000110 89 44 08 0f b6 c2 c0 e8 02 66 89 04 66 a1 60 7c |.D.......f..f.`||
00000120 66 09 c0 75 4e 66 a1 5c 7c 66 31 d2 66 f7 34 88 |f..uNf.\|f1.f.4.|
00000130 d1 31 d2 66 f7 74 04 3b 44 08 7d 37 fe c1 88 c5 |.1.f.t.;D.}7....|
00000140 30 c0 c1 e8 02 08 c1 88 d0 5a 88 c6 bb 00 70 8e |0........Z....p.|
00000150 c3 31 db b8 01 02 cd 13 72 1e 8c c3 60 1e b9 00 |.1......r...`...|
00000160 01 8e db 31 f6 bf 00 80 8e c6 fc f3 a5 1f 61 ff |...1..........a.|
00000170 26 5a 7c be 8e 7d eb 03 be 9d 7d e8 34 00 be a2 |&Z|..}....}.4...|
00000180 7d e8 2e 00 cd 18 eb fe 47 52 55 42 20 00 47 65 |}.......GRUB .Ge|
00000190 6f 6d 00 48 61 72 64 20 44 69 73 6b 00 52 65 61 |om.Hard Disk.Rea|
000001a0 64 00 20 45 72 72 6f 72 0d 0a 00 bb 01 00 b4 0e |d. Error........|
000001b0 cd 10 ac 3c 00 75 f4 c3 91 b5 c0 25 00 00 80 20 |...<.u.....%... |
000001c0 21 00 07 7e 25 19 00 08 00 00 00 38 06 00 00 7e |!..~%......8...~|
000001d0 26 19 07 fe ff ff 00 40 06 00 00 40 89 12 00 fe |&......@...@....|
000001e0 ff ff 05 fe ff ff fe 87 8f 12 02 60 b3 12 00 00 |...........`....|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|

So then I went in and started to try to understand the logical structure of the code. I slopped around in here until I got the basic idea.

start:
0: eb 63 jmp FIRST_CODE

data1?:
2: 90 nop
3: d0 bc 00 7c sarb 0x7c00(%si)
7: fb sti
8: 8e c0 mov %ax,%es
a: 8e d8 mov %ax,%ds
c: 8b f4 mov %sp,%si
e: bf 00 06 mov $0x600,%di
11: b9 00 02 mov $0x200,%cx
14: fc cld
15: f3 a4 rep movsb %ds:(%si),%es:(%di)
17: ea 60 06 00 00 ljmp $0x0,$0x660
1c: 00 00 add %al,(%bx,%si)
1e: 00 00 add %al,(%bx,%si)

string1:
20: "RecoveryMgr "

data2:
2d: 98 d9 22
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4e: 0d 0a 00 00 00 00 57 00 00 00 ff ff 00 80 01 00 00 00 00 00 00 00 ff

FIRST_CODE:
65: fa cli
66: 90 nop
67: 90 nop
68: f6 c2 80 test $0x80,%dl
6b: 74 05 je 0x72
6d: f6 c2 70 test $0x70,%dl
70: 74 02 je 0x74
b:
72: b2 80 mov $0x80,%dl
c:
74: ea 79 7c 00 00 ljmp $0x0,$0x7c79 # leaves forever???

disable_interupts()
if dl!=70:
dl=80
longjump 0:7c79

d:
79: 31 c0 xor %ax,%ax
7b: 8e d8 mov %ax,%ds
7d: 8e d0 mov %ax,%ss
7f: bc 00 20 mov $0x2000,%sp
82: fb sti
83: a0 64 7c mov 0x7c64,%al
86: 3c ff cmp $0xff,%al
88: 74 02 je 0x8c
8a: 88 c2 mov %al,%dl

ax = 0
ds = 0
ss = 0
sp = 2000
al = &7c64 (presumably set up by first_code jump)
if al == ff:
goto e
dl = al

e:
8c: 52 push %dx
8d: bb 17 04 mov $0x417,%bx
90: 80 27 03 andb $0x3,(%bx)
93: 74 06 je 0x9b
95: be 88 7d mov $0x7d88,%si
98: e8 17 01 call 0x1b2

if *417 != 3:
string index = 7d88
print(dx)

CHECK DRIVE READ SECTORS:
9b: be 05 7c mov $0x7c05,%si
9e: b4 41 mov $0x41,%ah
a0: bb aa 55 mov $0x55aa,%bx
a3: cd 13 int $0x13
a5: 5a pop %dx
a6: 52 push %dx
a7: 72 3d jb 0xe6
a9: 81 fb 55 aa cmp $0xaa55,%bx
ad: 75 37 jne 0xe6
af: 83 e1 01 and $0x1,%cx
b2: 74 32 je 0xe6
b4: 31 c0 xor %ax,%ax
b6: 89 44 04 mov %ax,0x4(%si)
b9: 40 inc %ax
ba: 88 44 ff mov %al,-0x1(%si)
bd: 89 44 02 mov %ax,0x2(%si)
c0: c7 04 10 00 movw $0x10,(%si)
c4: 66 8b 1e 5c 7c mov 0x7c5c,%ebx
c9: 66 89 5c 08 mov %ebx,0x8(%si)
cd: 66 8b 1e 60 7c mov 0x7c60,%ebx
d2: 66 89 5c 0c mov %ebx,0xc(%si)
d6: c7 44 06 00 70 movw $0x7000,0x6(%si)
db: b4 42 mov $0x42,%ah
dd: cd 13 int $0x13
df: 72 05 jb 0xe6
e1: bb 00 70 mov $0x7000,%bx
e4: eb 76 jmp 0x15c

string index = 7c05
ah = 41 # function number for extensions check
bx = 55aa # constant for int
int 13 # bios interrupt (dl is drive index, 80 is 1st hdd)
twiddle
if CF: # Set On Not Present, Clear If Present
goto ERROR
if bx != aa55: # Should always be set to this
goto ERROR
if cx == 1: #Interface support bitmask: 1 - Device Access using the packet structure
goto ERROR
# build up DAP pointer at si
ah = 42
int 13 # Extended Read Sectors From Drive
if CF: # Set On Error, Clear If No Error
goto ERROR
bx = 7000
goto H

ERROR:
e6: b4 08 mov $0x8,%ah
e8: cd 13 int $0x13
ea: 73 0d jae 0xf9
ec: f6 c2 80 test $0x80,%dl
ef: 0f 84 d0 00 je 0x1c3
f3: be 93 7d mov $0x7d93,%si
f6: e9 82 00 jmp 0x17b

ah = 8
int 13 # read drive parameters
if CF: # parameter read error
goto I
if dl == 80 # drive 1
goto CHECK DRIVE READ SECTORS #try again?
FAIL("Hard Disk ")

I:
f9: 66 0f b6 c6 movzbl %dh,%eax
fd: 88 64 ff mov %ah,-0x1(%si)
100: 40 inc %ax
101: 66 89 44 04 mov %eax,0x4(%si)
105: 0f b6 d1 movzbw %cl,%dx
108: c1 e2 02 shl $0x2,%dx
10b: 88 e8 mov %ch,%al
10d: 88 f4 mov %dh,%ah
10f: 40 inc %ax
110: 89 44 08 mov %ax,0x8(%si)
113: 0f b6 c2 movzbw %dl,%ax
116: c0 e8 02 shr $0x2,%al
119: 66 89 04 mov %eax,(%si)
11c: 66 a1 60 7c mov 0x7c60,%eax
120: 66 09 c0 or %eax,%eax
123: 75 4e jne 0x173
125: 66 a1 5c 7c mov 0x7c5c,%eax
129: 66 31 d2 xor %edx,%edx
12c: 66 f7 34 divl (%si)
12f: 88 d1 mov %dl,%cl
131: 31 d2 xor %dx,%dx
133: 66 f7 74 04 divl 0x4(%si)
137: 3b 44 08 cmp 0x8(%si),%ax
13a: 7d 37 jge 0x173
13c: fe c1 inc %cl
13e: 88 c5 mov %al,%ch
140: 30 c0 xor %al,%al
142: c1 e8 02 shr $0x2,%ax
145: 08 c1 or %al,%cl
147: 88 d0 mov %dl,%al
149: 5a pop %dx
14a: 88 c6 mov %al,%dh
14c: bb 00 70 mov $0x7000,%bx
14f: 8e c3 mov %bx,%es
151: 31 db xor %bx,%bx
153: b8 01 02 mov $0x201,%ax
156: cd 13 int $0x13
158: 72 1e jb 0x178 #goto READ_FAIL
15a: 8c c3 mov %es,%bx

h:
15c: 60 pusha
15d: 1e push %ds
15e: b9 00 01 mov $0x100,%cx
161: 8e db mov %bx,%ds
163: 31 f6 xor %si,%si
165: bf 00 80 mov $0x8000,%di
168: 8e c6 mov %si,%es
16a: fc cld
16b: f3 a5 rep movsw %ds:(%si),%es:(%di)
16d: 1f pop %ds
16e: 61 popa
16f: ff 26 5a 7c jmp *0x7c5a
push all flags
push ds
cx = 100
ds = bx
si = 0
di = 8000
es = 0
clear direction flag
copy a string from bx to 8000
restore ds
restore flags
jump to 0x00 80 01 00

GEOM_FAIL:
173: be 8e 7d mov $0x7d8e,%si #"Geom "
176: eb 03 jmp 0x17b
FAIL("Geom ")


READ_FAIL:
178: be 9d 7d mov $0x7d9d,%si #"Read "
FAIL("Read ")

FAIL:
17b: e8 34 00 call 0x1b2
17e: be a2 7d mov $0x7da2,%si
181: e8 2e 00 call 0x1b2
184: cd 18 int $0x18
print()
string index = 7da2 #"Error\n"
print()
int 18 # boot failure

INIFINITE_LOOP:
186: eb fe jmp 0x186
goto INFINITE_LOOP

strings:
188: 47 52 55 42 20 00 "GRUB "
18e: 47 65 6f 6d 00 "Geom"
193: 48 61 72 64 20 44 69 73 6b 00 "Hard Disk"
19d: 52 65 61 64 00 "Read"
1a2: 20 45 72 72 6f 72 0d 0a 00 "Error\n"

printChar:
1ab: bb 01 00 mov $0x1,%bx
1ae: b4 0e mov $0xe,%ah
1b0: cd 10 int $0x10

#print al in blue
bx = 1 #blue
ah = e #teletype print
int 10 #bios interrupt

print:
1b2: ac lods %ds:(%si),%al
1b3: 3c 00 cmp $0x0,%al
1b5: 75 f4 jne 0x1ab
1b7: c3 ret

al = load string
if al == NULL:
return
else:
goto printChar
return

dont think anything jumps here...:
1b8: 91 xchg %ax,%cx
1b9: b5 c0 mov $0xc0,%ch
1bb: 25 00 00 and $0x0,%ax
1be: 80 20 21 andb $0x21,(%bx,%si)
1c1: 00 07 add %al,(%bx)

j:
1c3: 7e 25 jle 0x1ea
1c5: 19 00 sbb %ax,(%bx,%si)
1c7: 08 00 or %al,(%bx,%si)
1c9: 00 00 add %al,(%bx,%si)
1cb: 38 06 00 00 cmp %al,0x0
1cf: 7e 26 jle 0x1f7

IF (ZF==0) OR (SF<>OF):
goto R
....
IF (ZF==0) OR (SF<>OF):
goto WTF jump

some other data:
1d1: 19 07 fe ff ff 00 40 06 00 00 40 89 12 00 fe ff ff 05 fe ff ff fe 87 8f 12

r:
1ea: 02 60 b3 add -0x4d(%bx,%si),%ah
1ed: 12 00 adc (%bx,%si),%al <--- jump to 1f7, wtf?
...
o:
1fb: 00 00 add %al,(%bx,%si)
1fd: 00 55 aa add %dl,-0x56(%di)
p:
207: ?
q:
218: ?
I'd keep going but I have satiated my curiosity. I wonder if the source file is in grub or linux.

No comments:

Post a Comment