zoukankan      html  css  js  c++  java
  • 操作系统开发系列—12.d.扩充内核 ●

    现在把esp、GDT等内容放进内核中,我们现在可以用C语言了,只要能用C,我们就避免用汇编。

     下面看切换堆栈和GDT的关键代码:

    ; 导入函数
    extern	cstart
    
    ; 导入全局变量
    extern	gdt_ptr
    
    [SECTION .bss]
    StackSpace		resb	2 * 1024
    StackTop:		; 栈顶
    
    	; 把 esp 从 LOADER 挪到 KERNEL
    	mov	esp, StackTop	; 堆栈在 bss 段中
    
    	sgdt	[gdt_ptr]	; cstart() 中将会用到 gdt_ptr
    	call	cstart		; 在此函数中改变了gdt_ptr,让它指向新的GDT
    	lgdt	[gdt_ptr]	; 使用新的GDT
    

    最后这4个语句完成了切换堆栈和更换GDT的任务。StackTop定义在.bss段中,堆栈大小为2KB。

    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 */
    PUBLIC	DESCRIPTOR	gdt[GDT_SIZE];
    
    PUBLIC void cstart()
    {
    
    	disp_str("
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    "
    		 "-----"cstart" begins-----
    ");
    
    	/* 将 LOADER 中的 GDT 复制到新的 GDT 中 */
    	memcpy(&gdt,				   /* New 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]);
    	u32* p_gdt_base  = (u32*)(&gdt_ptr[2]);
    	*p_gdt_limit = GDT_SIZE * sizeof(DESCRIPTOR) - 1;
    	*p_gdt_base  = (u32)&gdt;
    }
    

    函数首先把位于Loader中的原GDT全部复制给新的GDT,然后把gdt_ptr中的内容换成新的GDT的基地址和界限。SGDT——保存全局描述符,gdt_ptr[2]的值本身就是个地址,所以前面带上(void*)表示是个指针。memcpy之所以用void*,是因为需要一个字节一个字节复制。

    编译:

    nasm boot.asm -o boot.bin

    nasm loader.asm -o loader.bin

    nasm -f elf -o kernel.o kernel.asm

    nasm -f elf -o string.o string.asm

    nasm -f elf -o kliba.o kliba.asm

    gcc -m32 -c -fno-builtin -o start.o start.c

    ----

    dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc

    sudo mount -o loop a.img /mnt/hgfs/

    sudo cp loader.bin /mnt/hgfs/ -v

    sudo umount /mnt/hgfs/

    ----

    ld -m elf_i386 -s -Ttext 0x30400 -o kernel.bin kernel.o string.o start.o kliba.o

    sudo mount -o loop a.img /mnt/hgfs/

    sudo cp kernel.bin /mnt/hgfs/ -v

    sudo umount /mnt/hgfs/

    运行结果如下:

    源码

  • 相关阅读:
    python list dict 去重的两种方式
    python 发送邮件
    mongo 查询总结
    vsftpd 安装配置
    简单配置 nginx 反向代理
    python 检查内存
    python ldap
    Centos 7 vsftpd ldap 配置
    centos7虚拟机开启端口后 外部不能访问的问题
    Linux下安装配置rocketmq (单个Master、双Master)
  • 原文地址:https://www.cnblogs.com/joey-hua/p/5404762.html
Copyright © 2011-2022 走看看