第4章 进入保护模式(设置GDT全局描述符表)
2011-09-04 16:14
162 查看
进入保护模式的步骤是:
1、关中断;
2、打开A20地址线,使之能访问1M以上的内存;
3、设置GDT; GDT知识可查看《Intel微处理器 第8版》p541 也可以查看 Intel开发手册
4、加载GDT;
5、进入保护模式,跳转到setup.s
boot.s的源代码如下所示
kernel.inc的源代码如下
1、关中断;
2、打开A20地址线,使之能访问1M以上的内存;
3、设置GDT; GDT知识可查看《Intel微处理器 第8版》p541 也可以查看 Intel开发手册
4、加载GDT;
5、进入保护模式,跳转到setup.s
boot.s的源代码如下所示
.text .global start .include "kernel.inc" .code16 start: jmp $0x0, $code msg: .string "1kos booting......\x0" code: movw $0xb800,%ax #显存地址在0xb8000 movw %ax, %es xorw %di, %di #es:di = 0xb8000 xorw %ax, %ax movw %ax, %ds #ds:si = msg movw $msg, %si cld #si和di自增 movb $0x07, %ah #字符属性:黑底白字 #打印msg信息 print_c: cmp $0x0, (%si) je load lodsb #ds:[si] -> al, ++si stosw #ax -> es:[di], di += 2 #al=字符 ah=属性 jmp print_c #读取kernel到0x7e00上 load: #设置临时栈 xorw %ax, %ax movw %ax, %ds # ds = 0x0 movw %ax, %ss # ss = 0x0,栈基址 movw $KERNEL_STACK_BOT,%sp # sp = 0x7c00,栈地址 #设置rd_kern的参数 #设置ES:BX参数 movw $KERNEL_START_SEGMENT, %ax movw %ax, %es # es = 0x7e0 xorw %bx, %bx # bx = 0x0, es:bx = 0x7e00 #读取的起始扇区号(逻辑扇区起始扇区号是0) movw $0x1, %si # si = 0x1 ,是rd_sect的参数 #读取1400个扇区,共700K movw $KERNEL_SECT_NUMBER, %cx #调用rd_kern函数 #读取700K的kernel到0x7e00上 call rd_kern #关中断 cli #探测内存情况,并把内存探测结果写入特定位置中 call check_mem #打开A20地址线 enable_a20: inb $0x64, %al testb $0x2, %al jnz enable_a20 movb $0xdf, %al outb %al, $0x64 #设置GDT lgdt gdt_48 #进入保护模式 movl %cr0, %eax orl $0x1, %eax movl %eax, %cr0 ljmp $CODE_SEL, $0x7e00 #============================================================== #函数名:rd_kern #功能:读取软驱A上连续多个扇区 #参数1: ES:BX 读取数据存放的目的地址 #参数2: SI 指定起始逻辑扇区号 #参数3: CX 欲读取的扇区数目 rd_kern: pushw %ax rd_k1: call rd_sect movw %es, %ax # addw $0x20, %ax # movw %ax, %es # es:bx += 512 incw %si # ++si loop rd_k1 # if(cx != 0) goto rd_k1; popw %ax ret #============================================================== #============================================================== #函数名:rd_sect #功能:读取软驱A上的1个扇区 #参数1: ES:BX 读取数据存放的目的地址 #参数2: SI 指定逻辑扇区号 rd_sect: pushw %ax pushw %dx pushw %cx pushw %bx movw %si, %ax movb $18, %bl divb %bl # al <-- (ax)/(bl) 的商 # ah <-- (ax)/(bl)的余数 incb %ah # 因为软驱的物理起始扇区号从1开始,而逻辑扇区号从0开始,所以要增1 movb %ah, %cl # 起始扇区号,(int 13H ah=02h 中断的参数) xorb %ah, %ah movb $2, %bl divb %bl movb %ah, %dh # 磁头号,(int 13H ah=02h 中断的参数) movb %al, %ch # 磁道号,(int 13H ah=02h 中断的参数) popw %bx re_rd: movb $0x2, %ah # 读磁盘中断 movb $1, %al # 读取1个扇区 movb $0x0, %dl # 读取软驱A int $0x13 jc re_rd popw %cx popw %dx popw %ax ret #============================================================== #============================================================== #函数名:check_mem #功能:使用E820方法探测内存大小 #参数1: eax #参数2: ebx #参数3: ecx #参数4: edx #参数5: es:di check_mem: pushl %eax pushl %ebx pushl %ecx pushl %edx pushw %es pushw %di xorw %ax, %ax movw %ax, %es movl $0x0, %ebx movw $E820MAP, %di 1: movl $0x0E820, %eax movl $20, %ecx movl $0x534D4150,%edx int $0x15 jc ck_fail addw $20, %di incl E820NR(,1) cmpl $0, %ebx jne 1b jmp ck_ok ck_fail: movl $0, E820NR(,1) ck_ok: popw %di popw %es popl %edx popl %ecx popl %ebx popl %eax ret #============================================================== .org 0x100, 0xff #============================================================== #gdt在内存中的地址是0x7c00 + 0x100 = 0x7d00 gdt: .quad 0x0000000000000000 #GDT表第一项为空 .word 0x0ffff #边界限制为4GB .word 0x0000 #基地址 = 0x00000000 .word 0x9a00 #代码段,可 读/执行 .word 0x00cf # 4K边界粒度;386 .word 0x0ffff #边界限制为4GB .word 0x0000 #基地址 = 0x00000000 .word 0x9200 #数据段,可 读/写 .word 0x00cf # 4K边界粒度;386 .quad 0x0000000000000000 #GDT表第四项备用 .quad 0x0000000000000000 #GDT表第五项备用 gdt_48: .word .-gdt-1 .long gdt #============================================================== .org 0x1fe, 0x90 .word 0xaa55
kernel.inc的源代码如下
.set CODE_SEL, 0x08 #内核代码段选择符 .set DATA_SEL, 0x10 #内核数据段选择符 .set KERNEL_SECT_NUMBER, 1400 #内核长度,以扇区为单位 .set KERNEL_STACK_BOT, 0x7c00 #内核堆栈 .set KERNEL_START_SEGMENT, 0x7e0 #内核起始段,也就是内核会被拷贝到0x7e00上 .set GDT_ADDR, 0x7d00 #GDT在内存中的地址 0x7d00 = 0x7c00 + 0x100 .set NR_SYSTEM_CALLS, 11 #现在系统调用的数目 .set USER_CODE_SEL, 0x07 #用户代码段选择符 .set USER_DATA_SEL, 0x0f #用户数据段选择符 .set E820NR , 0x0FFC #内存映射项个数,存放地址 .set E820MAP, 0x1000 #内存探测结果项,存放地址
相关文章推荐
- catia设置技巧教程:进入管理模式VS工程图模板(如何进入管理模式)
- 《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-有特权级转换-进入ring3-b)
- centos 实现登录系统时有选择的进入文字模式(3)图形模式(5)的menu.lst设置
- [Intel汇编-NASM]进入保护模式全过程
- NASM 纯汇编打造简单中文操作系统(2 init.asm初始化操作系统内存。进入32位保护模式)
- Fedora15设置开机进入终端模式
- boot.s进入保护模式
- <<Linux内核完全剖析 --基于0.12内核>>学习笔记 第4章 80x86保护模式及其编程 4.3 分段机制
- Activity设置为启动模式为singletask第二次进入activity getintent获取不到问题
- 自制操作系统Antz day02——进入保护模式 (上) jmp到保护模式
- [Intel汇编-NASM]进入保护模式之前的准备
- 设置vista和win7进入Debug模式
- 007-进入保护模式
- 进入保护模式
- Linux Kernel 2.6.37 启动过程:漫步进入保护模式
- 【电脑技巧】远程访问-注意设置关键步骤修改电源计划取消进入睡眠模式
- Fedora15设置开机进入终端模式
- 进入保护模式总结
- 自制操作系统Antz day03——进入保护模式 (中) 直接操作显存
- 自制操作系统Antz day05——深入理解保护模式与进入方法