自己动手写操作系统(四)

    今天主要接着(二)来看一下stage2.asm。stage2.asm的功能主要有下面几个:

    =============================

    1.将系统从实模式切换到保护模式

    2.找到core.sys(就是kernel)的位置,并且将core.sys导入内存

    3.跳转到core.sys的入口函数处

    =============================

    首先看一下代码流程

    call GDT_INSTALL

    GDT全局描述符表[span]在英特尔x86[span]系列处理器的80286[span]起,为了定义的特点使用不同的存储区,在程序执行期间,包括基地址,大小和访问权限,如可执行可写。这些内存区域被称为(英特尔的术语)。内存中段所在的位置不需要写入特殊标记,段的信息(基地址、界限、属性等)保存通过段描述符表进行。GDT正是最重要的描述符表,进入保护模式,至少要准备GDT。GDT主要存放操作系统和各任务公用的描述符,如公用的数据和代码段描述符、各任务的TSS描述符和LDT描述符。每8个字节的条目在GDT是一个描述符。进入保护模式后我们会用到这个东东。     

    call ENABLE_PMODE
    jmp GDT_CODE_DESC:STAGE3    ; far jump to fix CS
    进入保护模式,然后跳转到StageE,可以看一下GDT_CODE_DESC就是之前我们定义在GDT中的段。

    关键来看一下stage3中的处理:

STAGE3:
    ; set segment registers
    cli
    mov ax, GDT_DATA_DESC   ; set data segments to data selectors (0x10)
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov esp, 0x90000    ; stack begins from 0x90000

    ; map PDE and enable paging
    ;call ENABLE_PAGING ;asido中会在这里进行内存第1M的分页,但是这样做会导致进入kernel后内存分页比较麻烦,所以这里直接不做分页

    ; calculate memory size in Kb from in 16-bit returned BIOS
    push DWORD [MemKBHigh]
    push DWORD [MemKBLow]
    call MEM16_TO_MEM32_SIZE
    mov DWORD [MemorySize], eax

    ; calculate kernel size in sectors returned from in 16-bit FAT12 driver
    push DWORD [KernelImgSizeHigh]
    push DWORD [KernelImgSizeLow]
    call KRNL_SIZE_TO_INT32
    mov DWORD [KernelImgSize], eax

    ; load the kernel
    push KERNEL_RMODE_BASE
    call LOAD_ELF ;这里是从core.sys中查找到入口函数地址,然后存放到eax中

    ; and execute it!
    cli
    push DWORD KERNEL_PMODE_BASE ;core.sys的加载起始地址入栈,这些数据会作为参数传入入口函数
    push DWORD [KernelImgSize]
    push DWORD [MemorySize]

;we push gdt addr to main start
    ;push DWORD [LGDT_VAL]
;we push gdt addr to main end

    call eax ;eax中存的就是入口函数地址,所以直接跳转。
    add esp, 0x4


这里还有一个技巧,就是我们在编译core.sys的时候先将起始的地址设为了0x100000(参看arale/core/linker.ld),然后将core .sys导入的内存地址也设定为从0x100000,这样,就能保证从core.sys中解析出来的入口函数地址和实际的物理地址是对应的。网上有很多其他的方法,例如在编译的时候加入

-Ttext $(ENTRYPOINT)来指定入口函数地址等,但都不是很方便。个人觉得还是这个上面介绍的方法比较方便。

从call eax开始,我们就进入了core的处理流程了(也就是大家常说的kernel)。后续主要的精力会先放在内存管理这块。主要也是因为性能优化关系较大的还是内存这块,哈哈~~~~。最关心的优先学~~。

谢谢





     

猜你喜欢

转载自blog.csdn.net/wang_sun_1983/article/details/74058967