D_D系统构建-Loader的保护模式尝试

8 篇文章 0 订阅
3 篇文章 0 订阅

前面我们完成了boot(mbr)读取Loader的任务,但我们一直都 在实模式下验证的。

本章我们将尝试保护模式下运行下loader(本章工程归档百度网盘,直接取用:http://pan.baidu.com/s/1eSeTwMQ).

首先我们要改造下我们的Loader,最简单的肯定要包含保护模式需要的内容。

实模式下,地址访问实际是按照段寄存器:偏移进行的, 实际的物理地址=段寄存器*16+偏移,比如段寄存器为0x2000, 偏移为0x1000, 实际对就的物理地址:0x2000*16+0x1000=0x21000; 

但在进入保护模式下后,段寄存器的含义变化了,它引入了一个新的概念:段选择子,本质上它是一个索引,通过它找到这个段真正的起始地址(未开户分布时),找到后,计算物理地址=段起始地址+偏移地址。

先上代码(http://pan.baidu.com/s/1eSeTwMQ):

loader.asm

%include "base_phy.inc"    

section code align=16 vstart=0
jmp start
%include "filesystem.inc"
;;;;;;;;;;;栈区空间预留;;;;;;;
stack_rsv:
		times 1024 db 0
stack_top:

;;;;;;;;;;;数据区预留;;;;;;;;
loaderMsg     db  "loader is running...", 0ah,0dh;
loaderMsgLen  equ $-loaderMsg


gdt_tbl:    dw 0      ;gdt界限
            dd MACRO_GDT_ADDR ;gdt物理地址

;;;;;;;;;;;代码区;;;;;;;;
start:
    mov ax, cs
    mov ds, ax
    mov es, ax
	mov ss, ax
	mov ax, 0
	mov gs, ax
    
	;栈顶赋值
    mov sp, stack_top
	
    ;显示loader运行信息
    mov	cx, loaderMsgLen ; CX = 串长度
    push cx
    mov	cx, loaderMsg	
    push cx
    call showString
    pop cx
    pop cx
	
	jmp next
	
;showString(字符串地址,字符串长度)
;在当前当前光标处显示字符串信息
;字符串地址: bp+4
;字符串长度: bp+6
showString:
    push bp
    mov bp, sp

    pusha

    mov ax, 0x0300
    mov bx, 0
    int 0x10

    mov	cx, [bp+6] ; CX = 串长度
    mov	bp, [bp+4]	
    mov	ax, 0x1301		; AH = 0x13,  AL = 0x1
    mov	bx, 0x7			; 页号为0(BH = 0) 黑底白字(BL = 0x7)
    int	0x10			; int 0x10

    popa
    pop bp
    
    ret

next:
    ;安装gdt
    xor ebx, ebx
    mov ebx, [gdt_tbl+2]
	
    ;0#号描述符的槽位 
    mov dword [gs:ebx],0x0         
    mov dword [gs:ebx+0x04],0x0
    
    ;创建1#描述符,保护模式下的代码段描述符
    mov dword [gs:ebx+0x08],0x0000ffff    ;基地址为0,界限0xFFFFF,DPL=00 
    mov dword [gs:ebx+0x0c],0x00cf9800    ;4KB粒度,代码段描述符,向上扩展 
    
    ;创建2#描述符,保护模式下的数据段和堆栈段描述符 
    mov dword [gs:ebx+0x10],0x0000ffff    ;基地址为0,界限0xFFFFF,DPL=00
    mov dword [gs:ebx+0x14],0x00cf9200    ;4KB粒度,数据段描述符,向上扩展 
    
    ;初始化描述符表寄存器GDTR
    mov word [gdt_tbl],23             ;描述符表的界限   
    
    lgdt [gdt_tbl]
    in al,0x92                         ;南桥芯片内的端口 
    or al,0000_0010B
    out 0x92,al   
	
	;打开A20
	mov eax, cs
	shl eax,4
	add eax, flush
	mov dword [cs:Enter_32+2], eax     ;修改指令偏移地址
    	
    cli                                ;中断机制尚未工作
	
    mov eax,cr0                  
    or eax,1
    mov cr0,eax                        ;设置PE位
    
    ;以下进入保护模式... ...
Enter_32:
	
    jmp dword 0x0008:flush             ;16位的描述符选择子:32位偏移

    [bits 32]               
    flush:                                  
        mov eax,0x00010                    ;加载数据段(4GB)选择子
        mov ds,eax
        mov es,eax
        mov fs,eax
        mov gs,eax
        mov ss,eax                         ;加载堆栈段(4GB)选择子
        mov esp,0x7000                     ;堆栈指针
		jmp $


运行效果如下 :

首先先编译并安装 我们的Loader


再运行bochs



怎么样,从效果上来看和之前 的实模式下是一模一样的,可以说是没有任何差别。

但这也正好说明我们的保护模式是没有问题的,运行正常,否则如果修改有问题,后果你也懂的。


这段代码下章节我来解释下,其余改动不多,有些改动甚至非常规(比如96行,这 实际是直接在实模式下修改了指令区代码)




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值