这几天还是在学习《自己动手写操作系统》,终于将保护模式了了。
上来贴上代码:
%include "pm.inc"
org 0100h
xchg bx,bx
jmp START
[SECTION .gdt]
GDT_DEC: Descriptor 0 , 0 , 0
CODE32_DEC: Descriptor 0 ,Code32SegLen-1,DA_32+DA_CE
VIDEO_DEC: Descriptor 0b8000h , 0ffffh,DA_DRW
DATA32_DEC: Descriptor 0 ,Data32SegLen-1,DA_DRW
STACK32_DEC: Descriptor 0 ,StackTop ,DA_32+DA_DRW
EXTRA_DEC: Descriptor 050000h , 0ffffh ,DA_DRW
CODE16_DEC: Descriptor 0 , 0ffffh ,DA_CE
NORMAL_DEC: Descriptor 0 , 0ffffh ,DA_DRW
GdtLen equ $ - GDT_DEC
Gdtptr dw GdtLen-1 ;Length of GDT
dd 0 ;base of GDT
SelectorCode32 equ CODE32_DEC - GDT_DEC
SelectorVideo equ VIDEO_DEC - GDT_DEC
SelectorData equ DATA32_DEC - GDT_DEC
SelectorStack equ STACK32_DEC - GDT_DEC
SelectorExtra equ EXTRA_DEC - GDT_DEC
SelectorCode16 equ CODE16_DEC - GDT_DEC
SelectorNormal equ NORMAL_DEC - GDT_DEC
[SECTION .s16]
[BITS 16]
START:
mov ax,cs
mov ds,ax
mov ss,ax
mov es,ax
mov sp,100h
mov [BACK_TO_REAL+3],ax
mov [RealModeSp],sp
;load Code32Segment Base
xor eax,eax
mov ax,cs
shl eax,4
add eax,CODE32_SEG
mov [CODE32_DEC+2],ax
shr eax,16
mov [CODE32_DEC+4],al
mov [CODE32_DEC+7],ah
;load data segment
xor eax,eax
mov ax,ds
shl eax,4
add eax,DATA32_SEG
mov [DATA32_DEC+2],ax
shr eax,16
mov [DATA32_DEC+4],al
mov [DATA32_DEC+7],ah
;load stack segment base
xor eax,eax
mov ax,ss
shl eax,4
add eax,STACK_SEG
mov [STACK32_DEC+2],ax
shr eax,16
mov [STACK32_DEC+4],al
mov [STACK32_DEC+7],ah
;load code16 segment base
xor eax,eax
mov ax,cs
shl eax,4
add eax,CODE16_SEG
mov [CODE16_DEC+2],ax
shr eax,16
mov [CODE16_DEC+4],al
mov [CODE16_DEC+7],ah
;load GDT Base
xor eax,eax
mov ax,cs
shl eax,4
add eax,GDT_DEC
mov [Gdtptr+2],eax
lgdt [Gdtptr]
cli
in al,92h
or al,02h
out 92h,al
mov eax,cr0
or eax,01h
mov cr0,eax
jmp dword SelectorCode32:0 ;Enter to Protected mode!
ENTER_REAL_MODE:
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov fs,ax
mov gs,ax
mov sp,[RealModeSp]
in al,92h
and al,11111101b
out 92h,al
sti
;call BIOS int 10h to test if back to real
mov cx,22
mov bh,0
mov bl,89h
mov dx,1000h
mov bp,BackRealMeg
mov ah,13h
mov al,01h
int 10h
;back to dos
mov ax,4c00h
int 21h
[SECTION .p16]
ALIGN 32
[BITS 16]
CODE16_SEG:
mov ax,SelectorNormal
mov ds,ax
mov ss,ax
mov gs,ax
mov fs,ax
mov es,ax
mov eax,cr0
and eax,0feh
mov cr0,eax
BACK_TO_REAL:
jmp 0:ENTER_REAL_MODE
Code16SegLen equ $ - $$
[SECTION .s32]
ALIGN 32
[BITS 32]
DATA32_SEG:
Message: db "Welcome to Protected Mode!",0
MessageLen equ $ - Message
offMessage equ Message - $$
RealModeSp dw 0
Letters: db "ABCDEFGHIJKLMNOPQRSTUVWXYZ",0
offLetters equ Letters -$$
BackRealMeg: db "Welcome back to real!\n"
Data32SegLen equ $ - $$
[SECTION .stack]
ALIGN 32
[BITS 32]
STACK_SEG:
times 512 db 0
StackTop equ $ - STACK_SEG - 1
[SECTION .s32]
[BITS 32]
CODE32_SEG:
mov ax,SelectorVideoto
mov gs,ax
mov ax,SelectorData
mov ds,ax
mov ax,SelectorStack
mov ss,ax
mov esp,StackTop
mov ax,SelectorExtra
mov es,ax
call DispMessage
call DispReturn
call ReadFromExtraSeg
call WriteToExtraSeg
call ReadFromExtraSeg
jmp SelectorCode16:0
DispMessage:
mov ah,0ch
mov esi,offMessage
mov edi,(80*12+20)*2
mov ecx,MessageLen
.loop:
mov al,[esi]
mov [gs:edi],ax
add edi,2
inc esi
loop .loop
ret
ReadFromExtraSeg:
xor esi,esi
mov ecx,08h
.loop:
mov al,[es:esi]
call DispAlAsNum
inc esi
loop .loop
call DispReturn
ret
DispAlAsNum:
push ecx
push edx
mov ecx,02h
mov dl,al
shr al,4
mov ah,0ch
.loop:
and al,0fh
cmp al,09h
ja .letter
add al,'0'
jmp .Disp
.letter:
sub al,0ah
add al,'A'
.Disp:
mov [gs:edi],ax
mov al,dl
add edi,2
loop .loop
add edi,2
pop edx
pop ecx
ret
DispReturn:
push eax
push ebx
mov eax,edi
mov bl,160
div bl
and eax,0ffh
inc eax
mul bl
mov edi,eax
pop ebx
pop eax
ret
WriteToExtraSeg:
push esi
push edi
xor esi,esi
xor edi,edi
mov esi,offLetters
cld
.loop:
lodsb
test al,al
jz .ok
mov [es:edi],al
inc edi
loop .loop
.ok:
pop edi
pop esi
ret
Code32SegLen equ $ - $$
然后运行结果图:
这个程序先从实模式进入保护模式,然后从附加段中读数据并输出,再从数据段向附加段写数据,然后输出。最后返回实模式。
刚开始时,没注意,还是利用org 0x7c00开头,直接从该软驱启动,但是提示找不到启动设备。然后利用Hex Edit查看,发现 510 511 单元不是55 aa而是00 00 ,再查看源代码,可以发现这块已经被Stack占用,也就是说,我们得程序已经超过了512B,那么,只好利用其他东西(如Freedos)来做引导.最后将改程序放入其一个软驱中。在DOS中运行这个程序。
还有就是,在DOS中如果程序出问题了该怎么办,我一开始想到得是Debug,但是遗憾得是没有这个命令。所以只好另图他径。首先在Bochs配置文件中添加magic_break : enabled=1,然后在程序中利用xchg bx,bx来设置断点。当你运行改程序时,在这里会自动将控制权交给Bochs,然后你就可以在Bochs中调试了。
再后呢就是关于从保护模式跳入实模式得步骤:
1. 关中断, 因为一开始中断就关掉了, 这步可以省略
2. 将程序从一个32位的代码段转移到16位的代码段, 这个代码段的段界限必须是64KB, 即FFFFh, 就是程序中的
SelectorCode16描述的那个段
这个的作用是刷新CS寄存器, 使它符合实模式下cs寄存器的要求
3. 刷新数据段的寄存器, 包括DS, ES, FS, GS, SS, 使得它们也符合实模式下的要求, 就是mov ax,
SelectorNormal的作用, SelectorNormal的要求是:
Limit = 64KB ( 0FFFFh )
Byte granular = 0 ( G = 0 )
Expand up ( E = 0 )
Writable ( W = 1 )
Present ( P = 1 )
Base = any value
也就是说, SelectorNormal描述的段要完全符合实模式下的数据段的要求
4. 清Cr0的PE位, 真正的转换到实模式, 需要注意的是SelectorCode16描述的那个段中的代码仍然是保护模式下的, 只不过是16
位的代码
只有当PE位清0的时候, 才真正的转换到实模式, 这个时候, 需要有一个跳转, 真正的跳转到实模式下的代码段, 而这个跳转的寻址方式是实
模式寻址方式
5. 经过第4步的关键跳转, CS被更新成了真正的实模式下的段地址, 这个时候, 需要重新刷新数据段寄存器, 使他们工作在实模式下,
这些数据寄存器包括上述提到的所有的段寄存器, 即DS, ES, FS, GS, SS, 如果你不用它们的话, 就直接赋值为0也是可以的
6. 开中断, 这步完成之后, 就完全完成了保护模式到实模式的切换
此时,你可以调用dos中断返回dos操作系统, 书上就是这么做的
- 大小: 17.9 KB
分享到:
相关推荐
此外,【玩转手机最新版】还具有电池管理功能,智能分析电池使用情况,给出合理的充电建议和省电模式,延长手机的使用时间。 在隐私保护方面,软件提供密码保护、隐藏应用等功能,让用户能够更好地保护个人隐私。...
"玩转手机5.2.2注册版"是一款专为智能手机用户设计的应用程序,它集成了多种实用功能,旨在帮助用户更好地管理和优化他们的设备。在这款软件的5.2.2版本中,开发者可能对先前的版本进行了诸多改进,提升了性能、增强...
通过以上分析可以看出,《玩转电商系统深入剖析智慧电商平台》这本书不仅涵盖了电商平台的核心技术要点,还针对实际应用场景提出了具体的实践方案。无论是对于想要深入了解该领域的技术人员还是正在寻求解决方案的...
《零死角玩转STM32》是一本专为嵌入式开发者设计的全面教程,旨在帮助读者深入理解和熟练掌握STM32系列微控制器的使用。STM32是意法半导体(STMicroelectronics)推出的基于ARM Cortex-M内核的微控制器,广泛应用于...
"零死角玩转STM32"这套资料全面覆盖了STM32的学习路径,包括初级篇、中级篇、高级篇和系统篇,旨在帮助开发者从基础到深入全面掌握STM32的使用。 初级篇: 在这个阶段,学习者会了解STM32的基础知识,例如其架构、...
《轻松玩转ARM Cortex-M4微控制器 - 基于Kinetis K60》这本书是为想要深入了解和掌握Cortex-M4处理器以及基于K60芯片开发的工程师和爱好者量身打造的指南。Cortex-M4是ARM公司设计的一款高性能、低功耗的32位微控制...
"零死角玩转STM32+初级篇+中级篇+系统篇"是一套全面的学习资源,旨在帮助初学者和进阶者深入理解并熟练掌握STM32的开发应用。 初级篇通常会涵盖以下知识点: 1. **STM32基础知识**:介绍STM32系列的芯片特性,如...
《零死角玩转STM32》是一套全面深入学习STM32微控制器的教程,包含初级、中级、高级和系统四个篇章,总计486页,涵盖了从基础到进阶的全方位知识。这套教程旨在帮助读者从零开始,逐步掌握STM32的使用技巧和实战经验...
《11招玩转网络安全:用Python,更安全》是一本深入探讨如何利用Python语言提升网络安全防护能力的书籍。在当今数字化时代,网络安全已经成为企业和个人都必须关注的重要议题。Python因其简洁、强大的语法特性,成为...
"零死角玩转stm32-初级+中级+高级篇"是一套全面的学习资料,旨在帮助学习者从入门到精通掌握STM32的开发和应用。 在初级篇中,你将了解STM32的基础知识,包括: 1. **STM32系列概述**:介绍STM32的不同系列和它们的...
"零死角玩转STM32 初级篇 中级篇 高级篇 系统篇.zip"这个压缩包包含了对STM32从初级到高级的全面学习资料,旨在帮助在校大学生和相关工程人员深入理解和熟练运用STM32。 初级篇通常会从基础概念开始,讲解STM32的...
标题中的“玩转夏令营海报(PS素材资源 PSD源文件图片下载)”指的是这是一个用于设计夏令营海报的PSD素材资源包。PSD是Adobe Photoshop的原生文件格式,它保留了图像的所有图层、蒙版、通道、调整等细节,允许设计...
根据提供的标题、描述和标签,本文将围绕“智能手机全攻略玩转手机基本功”这一主题进行深入探讨。尽管部分内容给出的数字与符号无法提供具体线索,但我们可以基于标题和描述来构建一系列关于如何掌握智能手机使用的...
《玩转众筹》这本书深入浅出地解析了众筹的运作机制、策略和法律风险,为读者提供了一套全面的指南。 首先,众筹的核心在于“众”和“筹”。它打破了传统的融资模式,不再依赖银行或投资者,而是将资金来源分散到...
在玩转相册设置中,有几个关键点需要注意,它们涵盖了相册权限、相册封面、相册展示方式、相册照片排序以及相册回收站的使用。 首先,**相册权限设置**允许用户灵活控制谁可以看到他们的相册。系统默认设置为“所有...
《玩转Acegi:SpringSide中的安全框架实践》 Acegi Security是Spring社区早期的一个安全框架,它为Spring应用提供了全面的身份验证和授权服务。在本文中,我们将深入探讨Acegi Security的核心概念,并通过...
总的来说,《玩转路由器密码》提供了全面的指南,帮助读者理解和解决Cisco路由器的密码问题,确保网络管理的安全和效率。通过学习,读者不仅可以掌握密码恢复技巧,还能深化对路由器内部工作原理的理解。
本教程“菜鸟也能玩转Cisco路由器”旨在帮助初学者快速理解和掌握Cisco路由器的基本操作和配置,让你无论是在学习还是工作中都能游刃有余。 首先,了解Cisco路由器的基础知识至关重要。Cisco路由器是一种专门用于...