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,正好直接进入。
这种方法过于粗暴,这里重新修改了进入保护模式的方法,避免使用修改指令的方法(本文地址: 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,正好直接进入。
相关文章推荐
- 如何修改SQL Server 2000身份验证模式和系统管理员Sa的登录密码
- 构建嵌入式系统-主机/开发板调试模式的种类
- windows xp vista 7 不重装系统,修改AHCI模式
- 众核多计算模式系统的构建 - 全文
- 虚拟实现汉字系统----VVDOS -- 源码 -- 保护模式程序 - 1
- 面向模式构建软件系统架构
- 时间片轮询模式在构建单片机实时系统中的应用
- 构建个人博客系统三(修改DBUtil)
- 操作系统开发系列—12.b.从Loader跳入保护模式
- JongXie OS系统成功从实模式跳转到保护模式下运行
- 2013-02-23 -一个简单的实模式跳转到保护模式程序(无loader功能)
- 避免重装系统的情况下,修改IDE为ACHI模式(适合修改注册表后更改BIOS依然蓝屏) 2012/1/21
- 虚拟实现汉字系统----VVDOS -- 源码 -- 保护模式程序 - 3
- 时间片轮询模式在构建单片机实时系统中的应用
- Linux单用户模式修改root密码or禁止单用户模式增强系统安全
- 保护电脑系统时间不被修改
- linux开机失败,单用户模式下修改系统文件
- 第二章-Windows程序运行原理——(1) CPU保护模式和Windows系统
- Linux系统进入单用户模式修改root密码
- 保护模式下三个重要的系统表——GDT、LDT和IDT