- 论坛徽章:
- 11
|
本帖最后由 zylthinking 于 2010-11-08 11:18 编辑
如下代码:
3:
movl $swapper_pg_dir-__PAGE_OFFSET,%eax
movl %eax,%cr3 /* set the page table pointer.. */
movl %cr0,%eax
orl $0x80000000,%eax
movl %eax,%cr0 /* ..and set paging (PG) bit */
jmp 1f /* flush the prefetch-queue */
1:
movl $1f,%eax
jmp *%eax /* make sure eip is relocated */
1:
/* Set up the stack pointer */
lss stack_start,%esp
现在搞懂了, 不过还有一个问题不明白; 为什么要 jmp 两次, 一般解释是第一次清空预读指令缓存; 但是在绝对跳转之前清空有什么深意吗, 毕竟, jmp *%eax 也会顺带着清空
问题1,为什么 jmp 1f 不能将 eip 从物理地址转换成虚拟地址, movl $1f,%eax jmp *%eax 就可以?
是不是编译后, jmp 1f 中的 1f 被翻译成了相对于当前指令地址的相对偏移, 而 movl $1f,%eax 确实将 lss stack_start,%esp 的绝对地址存入了 eax?
问题2, 3: 1: 1: 这些标号在二进制 binary 中的值到底是什么, 是相对于binary 文件第一个字节的偏移, 还是相对于binary文件text段的第一个字节的偏移, 还是在这个偏移量上又加上 1MB(内核加载基地址)呢
问题3, 从 movl $swapper_pg_dir-__PAGE_OFFSET,%eax 看, 似乎在分页启动之前, $swapper_pg_dir 保存的就已经是 0xc0000000 以上的地址了, 这个地址是怎么得出的呢?
无论从相对于某个起始点的偏移量还是在偏移量上再加上基地址, 似乎都不能得到这个数字。 |
|