mysql 保护模式_玩转保护模式

这几天还是在学习《自己动手写操作系统》,终于将保护模式了了。

上来贴上代码:

%include "pm.inc"

org0100h

xchgbx,bx

jmpSTART

[SECTION .gdt]

GDT_DEC:Descriptor0,0,0

CODE32_DEC:Descriptor0,Code32SegLen-1,DA_32+DA_CE

VIDEO_DEC:Descriptor0b8000h,0ffffh,DA_DRW

DATA32_DEC:Descriptor0,Data32SegLen-1,DA_DRW

STACK32_DEC:Descriptor0,StackTop,DA_32+DA_DRW

EXTRA_DEC:Descriptor050000h,0ffffh,DA_DRW

CODE16_DEC:Descriptor0,0ffffh,DA_CE

NORMAL_DEC:Descriptor0,0ffffh,DA_DRW

GdtLenequ$ - GDT_DEC

GdtptrdwGdtLen-1;Length of GDT

dd0;base of GDT

SelectorCode32equCODE32_DEC- GDT_DEC

SelectorVideoequVIDEO_DEC- GDT_DEC

SelectorDataequDATA32_DEC - GDT_DEC

SelectorStackequSTACK32_DEC- GDT_DEC

SelectorExtraequEXTRA_DEC- GDT_DEC

SelectorCode16equCODE16_DEC- GDT_DEC

SelectorNormalequNORMAL_DEC- GDT_DEC

[SECTION .s16]

[BITS 16]

START:

movax,cs

movds,ax

movss,ax

moves,ax

movsp,100h

mov[BACK_TO_REAL+3],ax

mov[RealModeSp],sp

;load Code32Segment Base

xoreax,eax

movax,cs

shleax,4

addeax,CODE32_SEG

mov [CODE32_DEC+2],ax

shreax,16

mov[CODE32_DEC+4],al

mov[CODE32_DEC+7],ah

;load data segment

xoreax,eax

movax,ds

shleax,4

addeax,DATA32_SEG

mov[DATA32_DEC+2],ax

shreax,16

mov[DATA32_DEC+4],al

mov[DATA32_DEC+7],ah

;load stack segment base

xoreax,eax

movax,ss

shleax,4

addeax,STACK_SEG

mov[STACK32_DEC+2],ax

shreax,16

mov[STACK32_DEC+4],al

mov[STACK32_DEC+7],ah

;load code16 segment base

xoreax,eax

movax,cs

shleax,4

addeax,CODE16_SEG

mov[CODE16_DEC+2],ax

shreax,16

mov[CODE16_DEC+4],al

mov[CODE16_DEC+7],ah

;load GDT Base

xoreax,eax

movax,cs

shleax,4

addeax,GDT_DEC

mov [Gdtptr+2],eax

lgdt[Gdtptr]

cli

inal,92h

oral,02h

out92h,al

moveax,cr0

oreax,01h

movcr0,eax

jmpdwordSelectorCode32:0 ;Enter to Protected mode!

ENTER_REAL_MODE:

movax,cs

movds,ax

moves,ax

movss,ax

movfs,ax

movgs,ax

movsp,[RealModeSp]

inal,92h

andal,11111101b

out92h,al

sti

;call BIOS int 10h to test if back to real

movcx,22

movbh,0

movbl,89h

movdx,1000h

movbp,BackRealMeg

movah,13h

moval,01h

int10h

;back to dos

movax,4c00h

int21h

[SECTION .p16]

ALIGN 32

[BITS 16]

CODE16_SEG:

movax,SelectorNormal

movds,ax

movss,ax

movgs,ax

movfs,ax

moves,ax

moveax,cr0

andeax,0feh

movcr0,eax

BACK_TO_REAL:

jmp0:ENTER_REAL_MODE

Code16SegLenequ$ - $$

[SECTION .s32]

ALIGN32

[BITS 32]

DATA32_SEG:

Message:db "Welcome to Protected Mode!",0

MessageLenequ $ - Message

offMessage equ Message - $$

RealModeSpdw0

Letters:db "ABCDEFGHIJKLMNOPQRSTUVWXYZ",0

offLettersequLetters -$$

BackRealMeg: db "Welcome back to real!\n"

Data32SegLenequ $ - $$

[SECTION .stack]

ALIGN32

[BITS 32]

STACK_SEG:

times 512 db 0

StackTop equ$ - STACK_SEG - 1

[SECTION .s32]

[BITS 32]

CODE32_SEG:

movax,SelectorVideoto

movgs,ax

movax,SelectorData

movds,ax

movax,SelectorStack

movss,ax

movesp,StackTop

movax,SelectorExtra

moves,ax

callDispMessage

callDispReturn

callReadFromExtraSeg

callWriteToExtraSeg

callReadFromExtraSeg

jmpSelectorCode16:0

DispMessage:

movah,0ch

movesi,offMessage

movedi,(80*12+20)*2

movecx,MessageLen

.loop:

moval,[esi]

mov[gs:edi],ax

addedi,2

incesi

loop .loop

ret

ReadFromExtraSeg:

xoresi,esi

movecx,08h

.loop:

moval,[es:esi]

callDispAlAsNum

incesi

loop .loop

callDispReturn

ret

DispAlAsNum:

pushecx

pushedx

movecx,02h

movdl,al

shral,4

movah,0ch

.loop:

andal,0fh

cmpal,09h

ja.letter

addal,'0'

jmp.Disp

.letter:

subal,0ah

addal,'A'

.Disp:

mov[gs:edi],ax

moval,dl

addedi,2

loop.loop

addedi,2

popedx

popecx

ret

DispReturn:

pusheax

pushebx

moveax,edi

movbl,160

divbl

andeax,0ffh

inceax

mulbl

movedi,eax

popebx

popeax

ret

WriteToExtraSeg:

pushesi

pushedi

xoresi,esi

xoredi,edi

movesi,offLetters

cld

.loop:

lodsb

testal,al

jz.ok

mov[es:edi],al

incedi

loop.loop

.ok:

popedi

popesi

ret

Code32SegLenequ$ - $$

然后运行结果图:

6081040306ba4e8fa40272778d8c05d5.png

这个程序先从实模式进入保护模式,然后从附加段中读数据并输出,再从数据段向附加段写数据,然后输出。最后返回实模式。

刚开始时,没注意,还是利用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操作系统, 书上就是这么做的

2fd9255febc4252b8056ebff35750ffb.png

大小: 17.9 KB

1

0

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2012-04-07 14:54

浏览 1040

评论

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值