切换到保护模式

来源:互联网 发布:java调用本地库中方法 编辑:程序博客网 时间:2024/05/17 20:29

.model large
.586p
;******************
jump macro selecter,offsetv   ;16位偏移的段间直接转移指令的宏定义
  db 0eah
  dw offsetv
  dw selecter
endm
;******************
h_line macro x,y,re,col  ;写屏幕上任一行像素点
       local flg1,flg2,cag
       ;call page0

       mov bx,x
flg1:  push bx
       mov eax,y
       mov ecx,640
       mul ecx
       add eax,ebx
       mov ecx,10000h
       div ecx

       mov di,dx
       push di
       mov dx,ax
       push dx

       cmp dx,pg
       jnz cag
       jmp flg2

cag:   mov pg,dx
       mov ah,4fh
       mov al,05h
       mov bh,00h
       mov bl,00h
       pop dx
       push dx
       int 10h

     
flg2:  pop dx
       mov al,col
       pop di
       stosb
       pop bx
       inc bx     
       cmp bx,x+re
       jb flg1

      
endm
;****************
;*****************
descriptor struc  ;存储段描述符结构
  limitl dw 0     ;段界限
  basel  dw 0     ;段基(0--15)
  basem  db 0     ;段基(16--23)
  attributes dw 0 ;属性
  baseh db 0      ;段基(24--31)
descriptor ends
;*****************
echoch macro ascii ;显示字符
  mov ah,2
  mov dl,ascii
  int 21h
endm
;****************
pdesc struc     ;伪描述符结构
  limit dw 0
  base dd 0
pdesc ends
;*****************
atdw=92h
atdc=98h
;*****************
dseg segment use16

 gdt       label byte
 dummy     descriptor<>
 code      descriptor<0ffffh,,,atdc,>
 code_sel  =code-gdt
 datas     descriptor<0ffffh,0h,11h,atdw,0>
 datas_sel =datas-gdt
datad     descriptor<0ffffh,,,atdw,>
datad_sel =datas-gdt
gdtlen    =$-gdt
;
vgdtr     pdesc<gdtlen-1>
;
bufferlen =256
buffer    db bufferlen dup(0)
pg dw 0
dseg ends
;*******************
cseg segment use16
 assume cs:cseg,ds:dseg

 start:
   mov ax,dseg
   mov ds,ax

   mov bx,16
   mul bx                ;计算并设置GDT基地址
   add ax,offset gdt     ;界限已定义
   adc dx,0            
   mov word ptr vgdtr.base,ax
   mov word ptr vgdtr.base+2,dx

   mov ax,cs
   mul bx
   mov code.basel,ax     ;代码段开始偏移量为0
   mov code.basem,dl     ;界限已定义
   mov code.baseh,dh
;设计目标数据段描述符
   mov ax,ds
   mul bx                ;计算并设置数据段基地址
   add ax,offset buffer
   adc dx,0
   mov datad.basel,ax
   mov datad.basem,dl
   mov datad.baseh,dh

   lgdt fword ptr vgdtr  ;装入描述符

   cli

   call enableA20        ;打开地址线A20
;切换到保护方式
    mov eax,cr0
    or eax,1
    mov cr0,eax
 ;清指令预取队列,真正进入保护方式
    jump <code_sel>,<offset virtual>
    ;
virtual:
   mov ax,datas_sel
   mov ds,ax             ;加载源数据段描述符
   mov ax,datad_sel
   mov es,ax             ;加载目标数据段描述符
   cld
   xor si,si             ;设置初始指针
   xor di,di
   mov cx,bufferlen/4    ;设置4字节为单位的缓冲区长度
   rep movsd     ;传送.repz movsd 系统无法识别
;;*********************************
push a
mov ax,500
mov es,ax
mov bx,0
mov dl,0
mov dh,0
mov ch,0
mov cl,2
mov al,1
mov ah,2
int 0x13
popa

; pusha
; ;mov ax,dseg
; ;mov ds,ax
; mov ax,4f02h
; mov bx,118h
; int 10h
; mov eax,0a0000h
; mov es,ax
;
; h_line 20,20,100,0fh
; La:
; mov ah,10h
; int 16h
; cmp al,1bh
; jz kk1
; jmp La
; kk1:
; popa
;
;;*************************************
;返回实方式
   mov eax,cr0
   and eax,0fffffffeh
   mov cr0,eax
  
;清指令预取队列,进入实方式
    jump <seg real>,<offset real>
 real:
   call disableA20  ;关闭地址线A20
   sti              ;开中断
   ;
   mov ax,dseg      ;重置数据段寄存器
   mov ds,ax
   mov si,offset buffer
   cld              ;显示缓冲区内容
   mov bp,bufferlen/16
nextline:
   mov cx,16
nextch:
   lodsb
   push ax
   shr ax,4
   call toascii
   pop ax
   call toascii
   echoch al
   echoch ' '
   loop nextch
   echoch 0dh
   echoch 0ah
   dec bp
   jnz nextline
   ;
   mov ax,4c00h
   int 21h

 ;*****************
  toascii proc
  and al,0fh
  mov al,30h
  cmp al,3ah
  jb  kk
  add al,07h
  kk:
  toascii endp

;******************
enableA20 proc
  push ax
  in al,92h
  or al,02h
  out 92h,al
  pop ax
  ret
enableA20 endp

;***************
disableA20 proc
   push ax
   in al,92h
   and al,0fdh
   out 92h,al
   pop ax
   ret
disableA20  endp
;******************

cseg ends
end start