作业地址

While stopped at the above breakpoint, look at the registers and the stack contents: (gdb) info reg … (gdb) x/24x $esp … (gdb) Write a short (3-5 word) comment next to each non-zero value on the stack explaining what it is. Which part of the stack printout is actually the stack? (Hint: not all of it.)

You might find it convenient to consult the files bootasm.S, bootmain.c, and bootblock.asm (which contains the output of the compiler/assembler). The reference page has pointers to x86 assembly documentation, if you are wondering about the semantics of a particular instruction. Your goal is to understand and explain the contents of the stack that you saw above, just after entering the xv6 kernel. One way to achieve this would be to observe how and where the stack gets setup during early boot and then track the changes to the stack up until the point you are interested in. Here are some questions to help you along:

S1

Begin by restarting qemu and gdb, and set a break-point at 0x7c00, the start of the boot block (bootasm.S). Single step through the instructions (type si at the gdb prompt). Where in bootasm.S is the stack pointer initialized? (Single step until you see an instruction that moves a value into %esp, the register for the stack pointer.)

栈的初始值为 0x6f200x6f20 中存储的数据为 0xf000d239

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(gdb) b *0x7c00
Breakpoint 1 at 0x7c00
(gdb) c
Continuing.
[   0:7c00] => 0x7c00:  cli

Breakpoint 1, 0x00007c00 in ?? ()
(gdb) si
[   0:7c01] => 0x7c01:  cld
0x00007c01 in ?? ()
(gdb) i r
eax            0xaa55   43605
ecx            0x0      0
edx            0x80     128
ebx            0x0      0
esp            0x6f20   0x6f20
ebp            0x0      0x0
esi            0x0      0
edi            0x0      0
eip            0x7c01   0x7c01
eflags         0x2      [ ]
cs             0x0      0
ss             0x0      0
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) x/x 0x6f20
0x6f20: 0xf000d239

S2

Single step through the call to bootmain; what is on the stack now?

call bootmainesp0x7c00 即 boot block 起始地址

执行完 call bootmainesp0x7bfcbootmain 函数返回地址

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
(gdb) b *0x7c3e
Breakpoint 1 at 0x7c3e
(gdb) c
Continuing.
The target architecture is assumed to be i386
=> 0x7c3e:      mov    %eax,%ss

Breakpoint 1, 0x00007c3e in ?? ()
(gdb) si
=> 0x7c40:      mov    $0x7c00,%esp
0x00007c40 in ?? ()
(gdb) i r
eax            0x10     16
ecx            0x0      0
edx            0x80     128
ebx            0x0      0
esp            0x6f20   0x6f20
ebp            0x0      0x0
esi            0x0      0
edi            0x0      0
eip            0x7c40   0x7c40
eflags         0x6      [ PF ]
cs             0x8      8
ss             0x10     16
ds             0x10     16
es             0x10     16
fs             0x10     16
gs             0x10     16
(gdb) si
=> 0x7c45:      call   0x7d15
0x00007c45 in ?? ()
(gdb) i r
eax            0x10     16
ecx            0x0      0
edx            0x80     128
ebx            0x0      0
esp            0x7c00   0x7c00
ebp            0x0      0x0
esi            0x0      0
edi            0x0      0
eip            0x7c45   0x7c45
eflags         0x6      [ PF ]
cs             0x8      8
ss             0x10     16
ds             0x10     16
es             0x10     16
fs             0x10     16
gs             0x10     16
(gdb) si
=> 0x7d15:      push   %ebp
0x00007d15 in ?? ()
(gdb) i r
eax            0x10     16
ecx            0x0      0
edx            0x80     128
ebx            0x0      0
esp            0x7bfc   0x7bfc
ebp            0x0      0x0
esi            0x0      0
edi            0x0      0
eip            0x7d15   0x7d15
eflags         0x6      [ PF ]
cs             0x8      8
ss             0x10     16
ds             0x10     16
es             0x10     16
fs             0x10     16
gs             0x10     16

S3

What do the first assembly instructions of bootmain do to the stack? Look for bootmain in bootblock.asm.

ebp 压栈

1
7d15:	55                   	push   %ebp

S4

Continue tracing via gdb (using breakpoints if necessary – see hint below) and look for the call that changes eip to 0x10000c. What does that call do to the stack? (Hint: Think about what this call is trying to accomplish in the boot sequence and try to identify this point in bootmain.c, and the corresponding instruction in the bootmain code in bootblock.asm. This might help you set suitable breakpoints to speed things up.)

0x10000c 处设置断点然后看栈中数据和寄存器信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
(gdb) b *0x0010000c
Breakpoint 2 at 0x10000c
(gdb) c
Continuing.
=> 0x10000c:    mov    %cr4,%eax

Thread 1 hit Breakpoint 2, 0x0010000c in ?? ()
(gdb) i r
eax            0x0      0
ecx            0x0      0
edx            0x1f0    496
ebx            0x10074  65652
esp            0x7bdc   0x7bdc
ebp            0x7bf8   0x7bf8
esi            0x10074  65652
edi            0x0      0
eip            0x10000c 0x10000c
eflags         0x46     [ PF ZF ]
cs             0x8      8
ss             0x10     16
ds             0x10     16
es             0x10     16
fs             0x0      0
gs             0x0      0
(gdb) x/24x $esp
0x7bdc: 0x00007d8d      0x00000000      0x00000000      0x00000000
0x7bec: 0x00000000      0x00000000      0x00000000      0x00000000
0x7bfc: 0x00007c4d      0x8ec031fa      0x8ec08ed8      0xa864e4d0
0x7c0c: 0xb0fa7502      0xe464e6d1      0x7502a864      0xe6dfb0fa
0x7c1c: 0x16010f60      0x200f7c78      0xc88366c0      0xc0220f01
0x7c2c: 0x087c31ea      0x10b86600      0x8ed88e00      0x66d08ec0

0x7c00 向下增长,大于 0x7cv00 的地址存储 BIOS 和 boot loader 代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
0x7bdc: 0x00007d8d  // function return address after calling kernel
0x7be0: 0x00000000  // reserved value
0x7be4: 0x00000000  // reserved value
0x7be8: 0x00000000  // reserved value
0x7bec: 0x00000000  // reserved value
0x7bf0: 0x00000000  // ebx's value when calling bootmain
0x7bf4: 0x00000000  // esi's value when calling bootmain
0x7bf8: 0x00000000  // edi's value when calling bootmain
0x7bfc: 0x00007c4d  // function return address after calling bootmain
0x7c00: 0x8ec031fa  // cli (The following is instructions of bootblock)
0x7c04: 0x8ec08ed8
0x7c08: 0xa864e4d0
0x7c0c: 0xb0fa7502
0x7c10: 0xe464e6d1
0x7c14: 0x7502a864
0x7c18: 0xe6dfb0fa
0x7c1c: 0x16010f60
0x7c20: 0x200f7c78
0x7c24: 0xc88366c0
0x7c28: 0xc0220f01
0x7c2c: 0x087c31ea
0x7c30: 0x10b86600
0x7c34: 0x8ed88e00
0x7c38: 0x66d08ec0