扩充内核 start.c 、kernel.asm详细解释

在前面堆栈,esp,GDT等内容还在Loader中,为了方便控制,我们得把它们放进内核才行。

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                            start.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                                                    Forrest Yu, 2005
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include "type.h"
#include "const.h"
#include "protect.h"

PUBLIC void* memcpy(void* pDst, void* pSrc, int iSize);

PUBLIC void disp_str(char * pszInfo);                                                          //定义了两个函数

PUBLIC u8  gdt_ptr[6]; /* 0~15:Limit  16~47:Base */                                 //定义了一个gdt_ptr数组,6个U8大小,一共48个字节 gdt_ptr[0]limit

                                                                                                                  gdt_ptr[2]gdt基址
PUBLIC DESCRIPTOR gdt[GDT_SIZE];                                                          //定义了一个全局gdt表 128*64字节大小

PUBLIC void cstart()
{

 disp_str("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"                                             
   "-----\"cstart\" begins-----\n");

 /* 将 LOADER 中的 GDT 复制到新的 GDT 中 */
 memcpy(&gdt,       /* New GDT */                                                                //把原来的gdt拷贝到现在的gdt中
        (void*)(*((u32*)(&gdt_ptr[2]))),    /* Base  of Old GDT */
        *((u16*)(&gdt_ptr[0])) + 1    /* Limit of Old GDT */
  );
 /* gdt_ptr[6] 共 6 个字节:0~15:Limit  16~47:Base。用作 sgdt/lgdt 的参数。*/
 u16* p_gdt_limit = (u16*)(&gdt_ptr[0]);                                                      //定义了两个指针,p_gdt_limit,并指向gdt_ptr[0]这个地址
 u32* p_gdt_base  = (u32*)(&gdt_ptr[2]);                                                    //                       p_gdt_base,指向gdt_ptr[2]这个地址
 *p_gdt_limit = GDT_SIZE * sizeof(DESCRIPTOR) - 1;                                   //  由这两个指针,对gdt_ptr[0]、gdt_ptr[2]分别赋值,这时gdt_ptr
 *p_gdt_base  = (u32)&gdt;                                                                        //   就得到新的值,基址指向新定义的gdt表。
}

--------------------------------------------------------------------------------------------------------------------------------------------------------------

kernel.asm

SELECTOR_KERNEL_CS equ 8 //如果按楼主的写法:a equ 8  jmp a:b 这里的8指的是偏移,即相对于GDT首地址的偏移是8个字节。

extern cstart                          // 导入函数

extern gdt_ptr                        //导入全局变量

[SECTION .bss]                      //bssBSS(Block Started by Symbol)通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。
StackSpace  resb 2 * 1024   // 注意和数据段的区别,BSS存放的是未初始化的全局变量和静态变量,数据段存放的是初始化后的全局变量和静态变量。
StackTop:  ; 栈顶

[section .text]                       // 代码在此

global _start                         // 导出 _start

_start:

; 把 esp 从 LOADER 挪到 KERNEL
 mov esp, StackTop ; 堆栈在 bss 段中                         //转移esp

 sgdt [gdt_ptr] ; cstart() 中将会用到 gdt_ptr               //保存gdt寄存器到[gdt_ptr],gdt_ptr是一个数组,gdt_ptr就是这个数组的首地址
 call cstart                                                              //  在此函数中改变了gdt_ptr,让它指向新的GDT 
 lgdt [gdt_ptr]                                                         // 使用新的GDT

 ;lidt [idt_ptr]

 jmp SELECTOR_KERNEL_CS:csinit
csinit:                                                                      // “这个跳转指令强制使用刚刚初始化的结构”——<<OS:D&I 2nd>> P90.

 push 0
 popfd                                                                     //Pop top of stack into EFLAGS

 hlt                                                                         //HLT 执行操作后,使机器暂停工作,使处理器CPU处于停机...

------------------------------------------------------------------------------------------------------------------------------------------------------------

原文链接: https://www.cnblogs.com/wanghj-dz/archive/2011/05/15/2046840.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    扩充内核 start.c 、kernel.asm详细解释

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/25509

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午3:21
下一篇 2023年2月8日 上午3:22

相关推荐