?? 386p2b1.asm
字號(hào):
;**********************************************************************
; 保護(hù)模式下的編程示例 陳家祺 1996.6
;
; 1 實(shí)模式進(jìn)入保護(hù)模式及保護(hù)模式返回實(shí)模式方法
; 2 保護(hù)模式下的指令操作(直接寫屏)
; * 環(huán)境: MASM6.0, DOS6.2, 80486主機(jī), Himem.sys, 不能裝栽Emm386.exe
;**********************************************************************
desc struc ;選擇器描述符結(jié)構(gòu)
limit_15_0 dw ? ;界限15-0
base_15_0 dw ? ;基地址15-0
base_23_16 db ? ;基地址23-16
access db ? ;訪問(wèn)權(quán)
gran db ? ;粒度,類型,界限19-16
base_31_24 db ? ;基地址31-24
desc ends
dos_data segment word public 'data' ;數(shù)據(jù)段
save_gdt dw 4 dup (?) ;GDT保存區(qū)
save_ss dw ? ;SS保存區(qū)
dtsize dw ? ;設(shè)置GDTR用
dtload dw ?
dw ?
; ***** GDT 描述符表 *****
gdt_def equ $
desc < > ;空描述符
gdt_kcs desc <0ffffh,0000h,00h,9ah,0fh,00h> ;00000 - fffffH (1Mb)
gdt_kds desc <0ffffh,0000h,00h,92h,0fh,00h> ;00000 - fffffH (1Mb)
gdt_kss desc <00000h,0000h,00h,96h,00h,00h>
gdt_uds desc <0ffffh,0000h,00h,92h,0fh,00h> ;00000 - fffffH (1Mb)
gdt_size equ $-gdt_def
dos_data ends
dos_stack segment stack para 'stack' ;堆棧段
db 1024 dup (0)
dos_stack_sp dw 0
dos_stack ends
dos_code segment word public 'code' ;代碼段
assume cs:dos_code, ds:dos_data, ss:dos_stack
gdt_kcs_sel equ 08h ; CS選擇器
gdt_kds_sel equ 10h ; DS選擇器
gdt_kss_sel equ 18h ; SS選擇器
gdt_uds_sel equ 20h ; 用戶DS選擇器
main proc near
start :
mov ax,dos_data
mov ds,ax ; 設(shè)置DS
cli
mov ax,dos_stack
mov ss,ax ; 設(shè)置SS
mov save_ss,ax ; 保存SS
mov sp,offset dos_stack_sp ; 定義堆棧
call prot ; 調(diào)用保護(hù)模式操作子程
sti
mov ah,0
int 16h ; BIOS鍵盤中斷調(diào)用,等待按鍵!
mov ah,4ch
int 21h ; 返回DOS!
main endp
prot proc near
.386p
SGDT fword ptr save_gdt ; 保存原GDT
mov di,offset gdt_kcs ; 設(shè)置CS描述符的基地址
mov ax,cs ; 將實(shí)模式DOS的段地址
call copy_desc ; 換算為線性基地址
mov di,offset gdt_kds ; 設(shè)置DS描述符的基地址
mov ax,ds ; 將實(shí)模式DOS的段地址
call copy_desc ; 換算為線性基地址
mov di,offset gdt_kss ; 設(shè)置SS描述符的基地址
mov ax,ss ; 將實(shí)模式DOS的段地址
call copy_desc ; 換算為線性基地址
mov ax,ds ; 計(jì)算GTD表的線性地址
mov cx,10h
mul cx
add ax,offset gdt_def
adc dx,0
mov dtload,ax
mov dtload+2,dx
mov dtsize,gdt_size-1
LGDT fword ptr dtsize ; 裝載GDT
mov eax,cr0
or al,1 ; 設(shè)置控制寄存器CR0的PE位
mov cr0,eax ; 進(jìn)入保護(hù)模式
; ***** 進(jìn)入保護(hù)模式 ******
db 0eah ; 清除指令隊(duì)列,
dw offset prot_user ; CS=gdt_kcs_sel(保護(hù)模式碼段)
dw gdt_kcs_sel
prot_user:
call vram_disp ; 調(diào)用保護(hù)模式下顯示子程
mov eax,cr0
and al,0feh ;清除控制寄存器CR0的PE位
mov cr0,eax ;切換到實(shí)模式
db 0eah ;清除指令隊(duì)列,CS=dos_code(實(shí)模式碼段)
dw offset real_mode
dw dos_code
; ***** 退出保護(hù)模式 *****
real_mode:
mov ax,dos_data
mov ds,ax
LGDT fword ptr save_gdt ;恢復(fù)原GDT
mov ss,save_ss ;恢復(fù)堆棧段
ret
prot endp
vram_disp proc near ;保護(hù)模式下顯示子程
pushad
mov ax,gdt_uds_sel
mov ds,ax
mov cx,80*25 ;直接寫屏.
mov ebx,0b8000h
mov ah,17h ;字符顏色屬性,藍(lán)底白字
mov al,'A' ;顯示字符'A'
l1: mov [ebx],ax
add ebx,2
loop l1
popad
ret
vram_disp endp
copy_desc proc near ;設(shè)置GDT描述符的基地址
mov cx,10h ;將實(shí)模式DOS的段地址
mul cx ;換算為線性地址
mov [di].base_15_0,ax ;存入GDT描述符中
mov [di].base_23_16 ,dl
ret
copy_desc endp
dos_code ends
end start
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -