操作系统开发系列—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("\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 */
(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/
运行结果如下:

【源码】
操作系统开发系列—12.d.扩充内核 ●的更多相关文章
- 操作系统开发系列—12.f.在内核中添加中断处理 ●
因为CPU只有一个,同一时刻要么是客户进程在运行,要么是操作系统在运行,如果实现进程,需要一种控制权转换机制,这种机制便是中断. 要做的工作有两项:设置8259A和建立IDT. /*========= ...
- 操作系统开发系列—12.g.在内核中设置键盘中断
8259A虽然已经设置完成,但是我们还没有真正开始使用它呢. 所有的中断都会触发一个函数spurious_irq(),这个函数的定义如下: PUBLIC void spurious_irq(int i ...
- 操作系统开发系列—12.c.从Loader加载ELF内核,顺便解释下函数调用过程 ●
实际上,我们要做的工作是根据内核的Program header table的信息进行类似下面这个C语言语句的内存复制: memcpy(p_vaddr, BaseOfLoaderPhyAddr+p_of ...
- 操作系统开发系列—12.a.从Loader到内核 ●
Loader要做两项工作,我们先来做第一项,把内核加载到内存: 1.加载内核到内存. 2.跳入保护模式. 首先编译无内核时: nasm boot.asm -o boot.bin nasm loader ...
- 操作系统开发系列—12.b.从Loader跳入保护模式
现在,内核已经被我们加载进内存了,该是跳入保护模式的时候了. 首先是GDT以及对应的选择子,我们只定义三个描述符,分别是一个0~4GB的可执行段.一个0~4GB的可读写段和一个指向显存开始地址的段: ...
- 操作系统开发系列—12.e.Makefile
先来看一个简单的Makefile,我们把它放在目录/boot下,可以用来编译boot.bin和loader.bin. # Makefile for boot # Programs, flags, et ...
- 操作系统开发系列—10.内核HelloWorld ●
a.我们先来体验一下在Linux下用汇编编程的感觉,见代码 [section .data] ; 数据在此 strHello db "Hello, world!", 0Ah STRL ...
- 操作系统开发系列—9.Loader
一个操作系统从开机到开始运行,大致经历“引导—>加载内核入内存—>跳入保护模式—>开始执行内核”这样一个过程.也就是说,在内核开始执行之前不但要加载内核,而且还有准备保护模式等一系列 ...
- 操作系统开发系列—4.LDT
一直以来,我们把所有的段描述符都放在GDT中,而不管它属于内核还是用户程序,为了有效地在任务之间实施隔离,处理器建议每个任务都应当具有自己的描述符表,称为局部描述符表LDT,并且把专属于自己的那些段放 ...
随机推荐
- eclipse中断点调试debug
几乎没有用过debug模式,每次想要知道结果都是sysou一下.记得曾经问乱码问题,jfinal说打断点调试看在哪里出错.简单记下普通调试. 1.在需要查看的地方打断点,方法是在行号右侧双击. 2.运 ...
- 扩展Exception,增加判断Exception是否为SQL引用约束异常方法!
在设计数据表时,如果将某些列设置为关联其它表的外键,那么如果对其进行增加.修改操作时,其关联表若没有相匹配的记录则报错,或者在对其关联表进行删除时,也会报错,这就是外键约束的作用,当然除了外键还有许多 ...
- 移动端中pagehide、pageshow的应用
闲话少叙,来进入场景:订单提交页面,各种积分礼品卡规则都算好了,用户提交表单开始支付,支付完成进入成功提示页面,这是绝大部分网站的付款体验吧,那么问题来了,web移动端中进入成功提示页后,用户点击浏览 ...
- 编写Chrome扩展程序
Chrome的扩展程序很多,也很容易入门,可以来简单实现一下 看看,慢慢就能实现出一个扩展程序来 每个扩展程序应用一般会包含: 一个manifest清单文件 html文件 js文件 其他文件等 可以看 ...
- MVC过滤器的用法
APS.NET MVC中的每一个请求,都会分配给相应的控制器和对应的行为方法去处理,而在这些处理的前前后后如果想再加一些额外的逻辑处理.这时候就用到了过滤器. 在Asp.netMvc中当你有以下及类似 ...
- 自己写的一个简单的jQuery提示插件
代码: /** * 2014年11月13日 * 提示插件 */ (function ($) { $.fn.tips = function (text) { var divtipsstyle = &qu ...
- JavaScript中的parseInt的进制问题
昨天帮原来同学写个js,碰见个问题,parseInt('08')的结果竟然是0后来突然想过来,是八进制的原因parseInt 方法 返回由字符串转换得到的整数.parseInt(numString, ...
- C#的变迁史 - C# 2.0篇
在此重申一下,本文仅代表个人观点,如有不妥之处,还请自己辨别. 第一代的值类型装箱与拆箱的效率极其低下,特别是在集合中的表现,所以第二代C#重点解决了装箱的问题,加入了泛型.1. 泛型 - 珍惜生命, ...
- csharp: DBNull and DateTime
/// <summary> /// /// </summary> /// <param name="dateTime"></param&g ...
- 【Java每日一题】20161118
package Nov2016; public class Ques1118 { public static final int NUM = 10000000; public static void ...