您的位置:首页 > 其它

D_D系统构建-loader保护模式修改

2017-10-08 22:38 141 查看
前面在loader进入保护模式时,使用了指令修改的方法,主要原因是虚拟地址从0开始,而跳转的地址是相对段内而言的,通过修改指令的方式来加上基地址。

这种方法过于粗暴,这里重新修改了进入保护模式的方法,避免使用修改指令的方法(本文地址: http://pan.baidu.com/s/1i53Tm5Z)。
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 ;描述符表的界限

;打开A20
lgdt [gdt_tbl]
in al,0x92 ;南桥芯片内的端口
or al,0000_0010B
out 0x92,al

cli ;中断机制尚未工作

mov eax,cr0
or eax,1
mov cr0,eax ;设置PE位

;以下进入保护模式... ...
Enter_32:

jmp dword 0x0008:flush ;16位的描述符选择子:32位偏移

rsv: times 4096-($-$$) db 0 ;

section code32 align=32 vstart=0x11000
[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 ;堆栈指针

mov byte [gs:0xB8000], 'L'
mov byte [gs:0xB8002], 'L'
mov byte [gs:0xB8004], 'L'
mov byte [gs:0xB8006], 'L'
jmp $
;halt


相比之前 有两点变化 :1. 106行新增加code32段,其虚拟地址从0x11000处开始。 2. 104行增加预留4096长度,保证code32段偏移地址是从0x11000开始
这样我们在使用段选择子0x8时,它的基地址为0,但偏移地址为0x11000,正好直接进入。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息