Skip to content

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 就自然而然跳过来了。