当前位置: 代码迷 >> 汇编语言 >> 没法跳转到保护模式,求解答!
  详细解决方案

没法跳转到保护模式,求解答!

热度:4534   发布时间:2013-02-26 00:00:00.0
无法跳转到保护模式,求解答!!
按照于渊书里的例子改了一下,结果发现跳转不到保护模式:

;------head.bin
org 0100h

BaseAddress equ 0

jmp START

%include "segment.inc"

BaseOfLoader equ 09000h ; Head.bin被加载的地址
BasePhyAddr equ BaseOfLoader*10h

;-----设置代码段、数据段描述符
LABEL_GDT: Descriptor 0, 0, 0 ; 第一个GDT不使用,必须为0
LABEL_DESC_CR: Descriptor 0, 0fffffh, PST_C_R | F_G | F_D ; 只读,4GB的32位代码段
LABEL_DESC_DRW: Descriptor 0, 0fffffh, PST_D_W | F_G | F_D ; 可写,4GB的32位数据段
LABEL_DESC_VEDIO: Descriptor 0B800h, 0fffffh, PST_D_W | F_G | F_D ; 可写,4GB的32位数据段

;-----设置lgdt操作数:6字节,低2字节段界限,高4字节段基地址
GdtLen equ $ - LABEL_GDT
GdtPtr dw GdtLen - 1
dd BasePhyAddr + LABEL_GDT  ; 此处为物理地址

;-----设置段选择符(其实就是Descriptor在GDT表中的序号)
Selector_C equ LABEL_DESC_CR-LABEL_GDT
Selector_D equ LABEL_DESC_DRW-LABEL_GDT
Selector_V equ LABEL_DESC_VEDIO-LABEL_GDT

START:

mov ax, 0B800h
mov gs, ax
mov ah, 0Fh ; 0000: 黑底    1111: 白字
mov al, 'J'
mov bx, ax
mov [gs:((80 * 0 + 20) * 2)], bx ; 屏幕第 0 行, 第 39 列。


;-----Initialize hardware environment----

xor eax, eax
lgdt [GdtPtr] ; 此时程序位于GDT表中(因为GdtPtr的基地址就为GDT的地址)

cli ; 关中断
in al,0x92 ; 找到A20 I/O端口
or al,00000010b ; 0x92快速A20 GATE格式如下:
; Bit 0 – 设成1来快速重设 (用于返回实模式)
; Bit 1 - 0: 关闭 A20; 1:开启 A20
; Bit 2 –制造商定义
; Bit 3 –电源口令(CMOS bytes 0x38-0x3f或0x36-0x3f). 0: 可访问 , 1:不可访问
; Bits 4-5 -制造商定义
; Bits 6-7 - 00: HDD 活动LED 灭;其他 "亮"
out 0x92,al ; 设置A20引脚

xor eax, eax
mov eax, cr0 ; 设置CR0的PE位为1
or eax, 1
mov cr0, eax


jmp dword Selector_C:(BaseOfLoader*10h + LABEL_PM_START) ; 表示跳转到代码段的LABEL_PM_START处

; jmp LABEL_PM_START:0


LABEL_PM_START:

mov ax, Selector_V
mov gs, ax
mov ah, 0Ch ; 0000: 黑底    1111: 白字
mov al, 'M'
mov [gs:((80 * 7 + 40) * 2)], ax ; 屏幕第 0 行, 第 39 列。

jmp $ ; 到此停住

用BOCHS调试的时候发现就是无法跳转到保护模式,不会显示字符‘M’,也不会将光标停留住。

已经困扰我很久了,跪求大神解答啊啊啊啊啊啊啊啊啊啊啊啊!

------解决方案--------------------------------------------------------

         ;代码清单11-1
         ;文件名:c11_mbr.asm
         ;文件说明:硬盘主引导扇区代码 
           ;创建日期:2011-5-16 19:54

         ;设置堆栈段和栈指针 
           mov ax,cs      
         mov ss,ax
         mov sp,0x7c00
      
         ;计算GDT所在的逻辑段地址 
           mov ax,[cs:gdt_base+0x7c00]        ;低16位 
           mov dx,[cs:gdt_base+0x7c00+0x02]   ;高16位