这段代码从保护模式回来了吗?????

A1157599735 2012-03-29 06:12:32
%include "pm.inc"
org 07c00h
jmp LABEL_BEGIN
[SECTION .gdt]
LABEL_GDT:Descriptor 0,0,0
LABEL_DESC_CODE32:Descriptor 0,SegCode32Len-1,DA_C+DA_32
LABEL_DESC_VIDEO:Descriptor 0B8000h,0ffffh,DA_DRW
LABEL_DESC_TEST:Descriptor 05000000h,0ffffh,DA_DRW
LABEL_DESC_DATA:Descriptor 0,DataLen-1,DA_DRW
LABEL_DESC_NORMAL:Descriptor 0,0ffffh,DA_DRW
GdtLen equ $-LABEL_GDT
GdtPtr:dw GdtLen-1
dd 0
;GDT选择子
SelectorCode32 equ LABEL_DESC_CODE32-LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO-LABEL_GDT
SelectorData equ LABEL_DESC_DATA-LABEL_GDT
SelectorTest equ LABEL_DESC_TEST-LABEL_GDT
SelectorNormal equ LABEL_DESC_NORMAL-LABEL_GDT
[SECTION .data]
ALIGN 32
[BITS 32]
LABEL_DATA:
BMSpRealValue: dw 0
OffsetMessage:
dd 'hello great',0
DataLen equ $-LABEL_DATA
[SECTION .s16]
[BITS 16]
LABEL_BEGIN:
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0100h
;存储SP值
mov [BMSpRealValue],sp
mov [LABEL_GO_BACK_REAL_MODE+3],ax
;初始化32位代码段描述符
xor eax,eax
mov ax,cs
shl eax,4
add eax,LABEL_SEG_CODE32
mov [LABEL_DESC_CODE32+2],ax
shr eax,16
mov [LABEL_DESC_CODE32+4],al
mov [LABEL_DESC_CODE32+7],ah
;初始化32位数据段描述符
xor eax,eax
mov ax,ds
shl ax,4
add eax,LABEL_DATA
mov [LABEL_DATA+2],ax
shr eax,16
mov [LABEL_DATA+4],al
mov [LABEL_DATA+7],ah
;准备加载GDT
xor eax,eax
mov ax,ds
shl eax,4
add eax,LABEL_GDT
mov [GdtPtr+2],eax
;加载GDT
lgdt [GdtPtr]
;关中断
cli
;打开地址总线
in al,92h
or al,00000010B
out 92h,al
;打开CR0
mov eax,cr0
or eax,1
mov cr0,eax
;真正进入保护模式
jmp dword SelectorCode32:0
;<<<<<<<<<<<<<<<<<<<回到实模式<<<<<<<<<<<<<<
LABEL_REAL_ENTRY:
mov ax,cs
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
;恢复实模式SP
mov sp,[BMSpRealValue];??????
;关闭a20地址线
in al,92h
and al,11111101B
out 92h,al
;开中断
sti
;返回dos
mov ax,4c00h
int 21h
[SECTION .s32]
[BITS 32]
LABEL_SEG_CODE32:
mov ax,SelectorVideo
mov gs,ax
mov ax,SelectorData
mov ds,ax
mov ax,SelectorTest
mov es,ax
mov al,'a'
mov [es:0],al
mov edi,(80*10+11)*2
mov al,[es:0]
mov ah,0ch
mov [gs:edi],ax
;开始返回16位
mov ax,SelectorNormal
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
;置cr0末位为0
mov eax,cr0
and al,11111110B
mov cr0,eax
;进入实模式段
LABEL_GO_BACK_REAL_MODE:
jmp 0:LABEL_REAL_ENTRY
SegCode32Len equ $-LABEL_SEG_CODE32
参考《自己动手写操作系统》的第三章。。
...全文
117 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
moon_cat 2012-04-28
  • 打赏
  • 举报
回复
回到实模式的条件是LIMIT全部是0XFFFFF,然后CS指向NORMAL SELECTOR,这样才能正常回来,不然直接PANIC!
树直屏 2012-04-05
  • 打赏
  • 举报
回复
看《自己动手写操作系统》还不是看《OrangeS一个操作系统的实现》
也是于渊写的
前者是使用windows的环境
后者是使用linux环境
楼上的说的对,判断是保护模式还是实模式,关键是看cr0的PE是否置位。
看到这段代码

置cr0末位为0
mov eax,cr0
and al,11111110B
mov cr0,eax

显然PE位置0,这就意味着已经进入实模式了
虽然进入实模式,但是代码段寄存器CS指向的依然保护模式的选择子
因为,我们需要把CS改为指向实模式的代码的地址
接着看一下代码

;进入实模式段
LABEL_GO_BACK_REAL_MODE:
jmp 0:LABEL_REAL_ENTRY
SegCode32Len equ $-LABEL_SEG_CODE32

jmp 0:LABEL_REAL_ENTRY 这一句跳转指令
使得CS指向0(即0x0000)
到此,实模式才能正常工作了
  • 打赏
  • 举报
回复
保护模式的标志就是cr0寄存器的PE位,别的都是浮云,pe位恢复后,就是实模式了。回到实模式后,计算机的寻址方式也恢复成8086一样了!

4,469

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧