ucore中的手动地址转换

本文探讨了如何在32位系统中通过ELF头文件和全局描述符表(GDT)正确加载和定位程序。作者解释了ELF文件结构的检查,以及如何通过临时GDT调整加载地址,以适应不同的物理和线性地址映射。重点在于理解地址转换和GDT在启动过程中的作用。
摘要由CSDN通过智能技术生成
#define ELFHDR          ((struct elfhdr *)0x10000)  

void
bootmain(void) {
    // read the 1st page off disk
    readseg((uintptr_t)ELFHDR, SECTSIZE * 8, 0);

    // is this a valid ELF?
    if (ELFHDR->e_magic != ELF_MAGIC) {
        goto bad;
    }

    struct proghdr *ph, *eph;

    // load each program segment (ignores ph flags)
    ph = (struct proghdr *)((uintptr_t)ELFHDR + ELFHDR->e_phoff);
    eph = ph + ELFHDR->e_phnum;
    for (; ph < eph; ph ++) {
        readseg(ph->p_va & 0xFFFFFF, ph->p_memsz, ph->p_offset);
    }

    // call the entry point from the ELF header
    // note: does not return
    // 
    ((void (*)(void))(ELFHDR->e_entry & 0xFFFFFF))();

bad:
    outw(0x8A00, 0x8A00);
    outw(0x8A00, 0x8E00);

    /* do nothing */
    while (1);
}

注意上边的两个0xFFFFFF,都是用于地址转换的,再找到kernel.ld的如下代码,可以看出,我们给程序的位置是ELFHDR,这是内核被加载到的物理地址,但是其线性地址却是0xC0100000,注意,不同的lab这个地址会不同,因此,程序入口也是一个0xC0100000+一定的偏移的值off,此时,我们的临时gdt转换完的地址仍是原值(0xC0100000+off),这样的物理地址是不对的,
与上一个0xFFFFFF就是正确的物理地址了,因为我们只是为了进入32位,临时建立了一个全局描述符表,这个描述符表的内容为了方便瞎整的。

SECTIONS {
    /* Load the kernel at this address: "." means the current address */
    . = 0xC0100000;
# Bootstrap GDT
.p2align 2                                          # force 4 byte alignment
gdt:
    SEG_NULLASM                                     # null seg
    SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)           # code seg for bootloader and kernel
    SEG_ASM(STA_W, 0x0, 0xffffffff)                 # data seg for bootloader and kernel

gdtdesc:
    .word 0x17                                      # sizeof(gdt) - 1
    .long gdt                                       # address gdt

要问我为什么不一开始就整个正确的,我也不知道为啥,反正就写成这样了,

.align 4
__gdt:
    SEG_NULL
    SEG_ASM(STA_X | STA_R, - KERNBASE, 0xFFFFFFFF)      # code segment
    SEG_ASM(STA_W, - KERNBASE, 0xFFFFFFFF)              # data segment
__gdtdesc:
    .word 0x17                                          # sizeof(__gdt) - 1
    .long REALLOC(__gdt)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值