一个lab1看了好几天,因为每天都有一些其它的事,用作业要交,要上课。但主要原因是自己对x86架构上面的内容了解太小,很多东西都看不太明白。只是勉强的把lab1过了一遍,后面肯定还要重新看,重新做实验的。
下面是看的过程中,翻译和记录一些内容:
程序主要运行的流程:
boot.S
main.c
entry.S
init.c
在gdg中输入 b *address 就会在monitor那里设置好断点
这样可以看printf是如何实现的。
用单步的方式来跟踪x86上的printf是如何实现的。
如何实现在输出文件时实现不同的颜色输出文字。
传统的方式是 通过在输入的文字中嵌入一些要解释的asciii,
这里涉及到的内容是关于vag display hardware的编程。如果你真的想搞搞这玩意,你可以尝试把vag hardware
switch到graphics mode,然后让console,显示text在 graphical frame buffer中
关于stack
堆栈这个玩意是因为了有c才出现的,现在看看detail,关于stack on x86,然后写一个新的 有用的kernel
显示函数。打印一个跟踪 stack的情况,当调用call时,就会把ip保存到stack中去,
有关问题:kernel在哪部分代码init 它的stack,stack放在memory的哪个地址。kernel是如何保留stack空间的。
还有栈的end在哪里
x86的stack pointer,esp 寄存器,指向stack top,因为是向下生长,所以总是指向地址最小的。所以在sp所指的空间的
下面,空间都是free的。push a value做了什么:先减,然后把值写到stack中,从这里看出x86的stack是满递减的生长方式
pop的时候,先弹出数据到registor,然后再加地址。
在32位的模式下,push pop都是对32的数进行操作。esp也是可以被4整除的,
我们的x86指令,如call指令,是“hard-wired”的利用esp,因为调用call时,cpu自动的把要返回的地址放到了esp指向的空间
call: esp--;放数到stack
esp说了,再说ebp,base pointer,作为对比,在软件上做了约定,与stack有关,下面是重点:
在进入c function时,要做一些准备工作,通过是保存一些上层函数的 函数指针,通过push到stack
其实就是push %ebp,然后马当前函数函数的指针 指向的栈的值copy到ebp 就是mov %esp ,%ebp
如果所有的函数都 按照这个convention来办事,这样在程序运行的任何一点,都是可以根据stack里保存的指针值返回的
这种convention是非常有用的,例如,当一个特别的函数 cause an assert failure or panic,因为你传递了错误的参数。
但是你不确定哪个参数是一个bad argument时,一个stack backtrace会帮你找到这个函数,
参数只有到了那个发生错误的函数,发生了错误才会出现bad arguement
stack backtrace:这是一种debug的方法,叫栈的回溯,可以比较容易找到哪个函数发生了错误。
课程要求自己实现一个mon_backtrace,这个函数的用法就是在每进入一层,就调用一下这个函数,就可以知道自己在哪一层。
int
mon_backtrace(int argc, char **argv, struct Trapframe *tf)
{
// Your code here.
return 0;
}
If int *p = (int*)100, then (int)p + 1 and (int)(p + 1) are different numbers: the first is 101 but the second is 104.
上面这个例子把指针 转变成integer,
尽管大多数c程序都不需要把指针和整形来回转化,都是操作系统经常要做这样的事。
当你看到一个memory address时,你要想想 它是integer还是pointer,确保你知道 这个数在做加法时,你知道正确的答案。