Kernel 2.4.0 之 head.S 为何用两次 jmp 刷新 EIP 寄存器

这篇博客深入探讨了Linux内核2.4.0中head.S文件中的两个令人困惑的jmp指令。博主通过分析汇编代码和内存映射,揭示了这两个跳转实际上并不必要,且可以安全删除,因为内核后续的执行流程会自然地将EIP更新为正确的值。文章详细阐述了分段、分页机制以及跳转指令在不同模式下的工作原理,对于理解内核启动过程和x86处理器工作方式有很好的帮助。
摘要由CSDN通过智能技术生成

在arch\i386\kernel\head.S文件中,自line 100开始有这么几行:

    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

我看了很久都不明白第一次跳转到底是为了什么,情景分析那本书上说这是为了刷新指令预取队列,我把Intel手册翻了个遍也没找到关于预取队列的详细信息,维基百科上介绍的也不够详细。

在我终于弄明白之后,写一写我的分析过程,这份博客写写改改,用时一下午加一晚上才完工,一边写一边发现了很多自己得过且过的问题,写博客的过程也是查资料的过程,还是比较累的,如果写的有错误,欢迎指出。下面分析的过程也是思考的过程。

首先从setup.S看起,在arch\i386\boot\setup.S中line 113处有这么几行代码:

code32_start:               # here loaders can put a different
                # start address for 32-bit code.
#ifndef __BIG_KERNEL__
    .long   0x1000      #   0x1000 = default for zImage
#else
    .long   0x100000    # 0x100000 = default for big kernel
#endif

因为我们编译的是bzImage,所以code32_start标号处的数值为0x100000,占用四字节。

再看line 532处的几行代码:

# we get the code32 start address and modify the below 'jmpi'
# (loader may have changed it)
movl    %cs:code32_start, %eax
movl    %eax, %cs:code32

在执行这些代码时CPU还处于实模式,所以CS里面是段基址,不是selector!第一句是把code32_start处的一个双字(四字节)装入eax,这个双字的值就是0x100000;然后第二句把eax即0x100000赋值到code32标号所指的内存位置里。那么这个位置在哪呢?请继续看下面line 719的代码:

# NOTE: For high loaded big kernels we need a
#   jmpi    0x100000,__KERNEL_CS
#
#   but we yet haven't reloaded the CS register, so the default size 
#   of the target offset still is 16 bit.
#       However, using an operant prefix (0x66), the CPU will properly
#   take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
#   Manual, Mixing 16-bit and 32-bit code, page 16-6)

    .byte 0x66, 0xea            # prefix + jmpi-opcode
code32: .long   0x1000              # will be set to 0x100000
                    # for big kernels
    .word   __KERNEL_CS #这个数字是0x10

0x100000这个数字最终被写到了code32

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值