head.s 汇编几个迷惑
本帖最后由 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,%eaxjmp *%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 以上的地址了, 这个地址是怎么得出的呢?
无论从相对于某个起始点的偏移量还是在偏移量上再加上基地址, 似乎都不能得到这个数字。 第 2, 3 个问题我想我明白了, 在编译内核的时候,0xc0000000 和 1MB 这两个值是都有指定的, 那么所有地址估计在编译器的安排下, 都已经静态赋值成正确的虚拟地址了 对。jmp 1f只是offset address jump。只是当前eip加上一个offset,达不到作者想要的目的。 另外, 还有一个问题, CPU 取值令是怎么一个取法, 比如一下指令
.org 0
push ebp
.org 1M
movl esp, ebp
.org 是伪指令, 是不是意味着 .org 不会产生任何机器指令, 那 地址计数器 是怎么变化的呢? 如果说 CPU 取下一条指令时不依赖地址计数器, 那CPU 怎么知道到哪里取下一条指令, 好歹两者之间隔着 1M 呢 对。jmp 1f只是offset address jump。只是当前eip加上一个offset,达不到作者想要的目的。
snail_314 发表于 2010-08-03 14:08 http://linux.chinaunix.net/bbs/images/common/back.gif
那为什么会有 jump 1f 呢, 据说是清空预读的指令, 问题是 jump 1f 后跟着的是 movl 1f, %eax, 还是物理地址空间, 不会有产生预读?
就算不产生预读, 后边那个 jump *%eax就不能清空预读指令了吗 另外, 还有一个问题, CPU 取值令是怎么一个取法, 比如一下指令
.org 0
push ebp
.org 1M
movl esp ...
zylthinking 发表于 2010-08-03 14:40 http://linux.chinaunix.net/bbs/images/common/back.gif
这个伪指令是编译前给编译器看的,就是说编译器直接给地址0的地方放 push 0 然后在1m的地址处放 movl esp...中间插上nop。
个人想法,不对请各位大侠指正。 LS说的有一个错误。中间不会插上NOP,而是全0。自己写个小程序然后用HEX EDITOR 看下就知道了。
其他是对的。
另外,LZ这段代码是在那个文件里的?也许本身的设计就是让PUSH EBP之后什么都没有而出错。 :em12::dizzy: 回复 1# zylthinking
这个问题在编译板块有人讨论过了.当时我的看法是第一次jmp清掉刷新pipeline,如果不这么做的话,jmp后面一个指令读操作数阶段仍然是实模式下取得的,所以,这里相当于让后面那个mov在保护模式下重做一次(把前面那次实模式下的pipeline的废掉) 回复zylthinking
这个问题在编译板块有人讨论过了.当时我的看法是第一次jmp清掉刷新pipeline,如 ...
snail_314 发表于 2010-11-08 11:37 http://linux.chinaunix.net/bbs/images/common/back.gif
1f 的值是多少呢, 如果作为一个符号, 那会在生成内核时设成虚拟地址空间的地址, 因此, 无论 缓存线在什么情况下读, 读到的应该都是虚拟地址,那么无论废掉与否, 都应该是正确的才是
页:
[1]
2