因为搞不太清楚栈内的变化,所以我花了超大功夫,从0x7c00 (the boot loader 开始)
一步一步观察,直到0x0010000c (内核开始)
,只是我没想到,这中间居然有将近5万条指令,着实让我震惊!
断点设在br *0x0010000c
,可以看到如下信息:
通过我的实验可以知道
0x7c00:8ec031fa
是执行完movl $start, %esp
后的结果,我本以为这是栈的开始,结果不是,下面那个才是!
0x7bfc:0x00007c4d
存的是call bootmain
指令的下一条指令的地址,或者说是返回地址
0x7bf8:0x0
存的是bootmain的调用者程序的栈帧基地址ebp:0x0
0x7bf4、0x7bf0、0x7bec:0x0
分别是保存edi、esi、ebx的值,都为0
0x7be8~0x7be0:0x0
是执行了sub $0xc, %esp
后的结果,我认为是留出给局部变量的
0x7bdc:0x00007db4
存的是 call *0x10018
(内核入口)指令的下一条指令的地址
下面是问答:
- 首先重新启动qemu和gdb,并将断点设置为0x7c00,即the boot block(bootasm.S)的起点。单步执行指令(在gdb提示符处键入si)。在bootasm.S中,堆栈指针初始化了吗?(单步执行,直到看到一条将值移动到堆栈指针寄存器%esp中的指令。)
答:堆栈指针初始化了。在bootasm.S中有一条指令是movl $start, %esp
就是在初始化堆栈指针,只是不知道为什么我没有找到movl %0x0, %ebp,但ebp依然等于0x0。 - 单步通过调用bootmain;现在堆栈上有什么?
答:此时堆栈上只有0x7c00:8ec031fa
与0x7bfc:0x00007c4d
- bootmain的第一个汇编指令对堆栈做什么?在bootblock.asm中查找bootmain。
答:第一个指令时是push %ebp
,用于保存bootmain的调用者的栈帧基指针ebp。 - 通过gdb继续跟踪(如果必要的话使用断点——请参阅下面的提示),并查找将eip更改为0x10000c的调用。这个调用对堆栈做了什么?(提示:考虑这个调用试图在引导序列中完成什么,并尝试在bootmain中识别这一点。,以及bootmain代码中相应的指令。这可能会帮助您设置适当的断点来加快速度。)
答:这个调用将该call指令的返回地址0x7db4
存入到栈0x7bdc(esp)
处
其他:
- 能改变esp值的一般是push、pop、lea(lea -0xc(ebx), %esp)、add、sub;
- rep stos %al, %es(%edi) 负责依次赋值
rep指令的目的是重复其后面的指令.ECX的值是重复的次数.
STOS指令的作用是将al中的值拷贝到ES:EDI指向的地址,edi每次自增 ???