10 进入 main 函数前的最后一跃!
你好,我是闪客。
这一讲,我们将欣赏从汇编语言跳转到 C 语言的最后几行代码,并且对整个第一部分做个回顾。
这样就跳跃到了主函数
上一讲我们设置好了idt、gdt、页表,还开启了保护模式。那么接下来,我们怎么跳到主函数呢?
来看看设置分页代码的那个地方(head.s 里),后面这个操作就是用来跳转到 main.c的。
after_page_tables:
push 0
push 0
push 0
push L6
push _main
jmp setup_paging
...
setup_paging:
...
ret
直接解释起来非常简单。
push 指令就是压栈,五个 push 指令过去后,栈会变成这个样子。

然后你要注意,setup_paging 最后一个指令是 ret,也就是我们上一讲设置分页的代码里的最后一个指令,形象地说它叫返回指令。不过 CPU 可没有那么聪明,它并不知道该返回到哪里执行,只是很机械地把栈顶的元素值当做返回地址,跳转去那里执行。
我再描述一下具体细节,CPU会把 esp 寄存器(栈顶地址)所指向的内存处的值,赋值给 eip 寄存器,而 cs:eip 就是 CPU 要执行的下一条指令的地址。而此时栈顶刚好是 main.c 里写的 main 函数的内存地址,是我们刚刚特意压入栈的,所以 CPU 就自然而然跳过来了。