⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pmstart1.asm

📁 保护模式下的编程。从实模式进入保护模式,8255并行输入并行输出,通过显存字符输出,K0=1返回实模式
💻 ASM
字号:
;pmstart1.asm
;从实模式进入保护模式,8255并行输入并行输出,通过显存字符输出,K0=1返回实模式
include pmstart1.inc
.386p
;--------------------------
;全局描述符表GDT
GdtSeg segment para use16 'GDT'
gdt  LABEL  BYTE
     Dummy  Desc <>            ;
     
     NormalSel=$-gdt
     Normal Desc   <0ffffh,,,92h,,>
     
     VideoSel=$-gdt
     Video Desc <0ffffh,8000h,0bh,92h,,>

effgdt   LABEL BYTE 
     TempCodeSel=$-gdt
     TempCode   Desc <0ffffh,TempCodeSeg,,98H,,>
     
     SysCodeSel=$-gdt
     Syscode    Desc <SysCodeLen-1,SysCodeSeg,,98H,,>
         
     SysDataSel=$-gdt
     SysData    Desc <0ffffh,SysDataSeg,,92H,,>
     
     SysStack0Sel=$-gdt
     SysStack   Desc <SysStack0Len-1,SysStack0Seg,,92h,,>
     
    ; VideoSel=$-gdt                          ;放在这个位置字符无法输出
    ; Video Desc <0ffffh,8000H,0BH,92H,,> 
     
     GDTNUM=($-effgdt)/(size Desc)
     GdtLen  =$-gdt    
GdtSeg   ends
;----------------------------
;中断描述符表IDT
;IdtSeg  segment 
;IDT  LABEL  BYTE

;IdtSeg  ends
;----------------------------
SysStack0Seg   SEGMENT PARA USE16               ;0级堆栈
SysSTACK0_POINTER=1024
                    DB      SysSTACK0_POINTER  DUP(0)
SysStack0Len=$
SysStack0Seg   ENDS

;-----------------
SysDataSeg segment para use16
hipm    db    '          Now it is in protected mode! '
hipm_len=$-hipm 
endpm   db    '          Exit from the protected mode! '
endpm_len=$-endpm 
SysDataSeg ends
;--------------------
SysCodeSeg  segment para use16
            assume cs:SysCodeSeg,ds:SysDataSeg
do_pm:
    mov ax,SysStack0Sel     ;;;;;;;;;;;;;;
    mov ss,ax
    mov sp,offset SysStack0Len     ;;;;;;;;;;;;;;;
    mov ax,SysDataSel
    mov ds,ax
    mov fs,ax
    mov gs,ax
    mov ax,VideoSel
    mov es,ax

        lea si,hipm             ;输出字符,进入保护模式
        mov cx,hipm_len        
        push  ax
        push  cx
        mov  al,1        ;行         
        mov cl,160
        mul cl
        mov di,ax
        pop  cx
        pop  ax
        call  far ptr  DispMess  
        
xx:        mov dx,0c40bh
        mov al,89h
        out dx,al
        mov dx,0c40ah                ;读8255C口
        in  al,dx
        mov dx,0c408h
        out dx,al
        test al,01h
        jz  xx
        
        lea si,endpm
        mov cx,endpm_len        
        push  ax
        push  cx
        mov  al,2        ;行         
        mov cl,160
        mul cl
        mov di,ax
        pop  cx
        pop  ax
        call  far ptr  DispMess
        JUMP16    TempCodeSel,<OFFSET ToReal>
    
DispMess proc         ;字符串显示
   push di
   cld
dispa1:
   lodsb
   mov ah,34h
   stosw
   loop dispa1
   pop di
   ret
   DispCopyLen=$-DispMess
DispMess endp   
    
SysCodeLen=$    
SysCodeSeg  ends   
;---------------------------
TempCodeSeg  segment para use16
       assume cs: TempCodeSeg
Virtual:
   JUMP16    SysCodeSel,<OFFSET do_pm>         
ToReal:
   mov ax,NormalSel
   mov ds,ax
   mov es,ax
   mov fs,ax
   mov gs,ax
   mov ss,ax
   mov eax,cr0; 退出保护方式。
   and eax,0fffffffeh
   mov cr0,eax
   jmp FAR ptr Real
TempCodeSeg    ends

;----------------------------------------------------
;实方式下的数据段
RDataSeg segment para use16
    V_GDTR         PDESC <GdtLen-1,>  ; 全局描述符表。
;    V_IDTR         PDESC <IdtLen-1,>  ; 中断描述符表。

;    RealIdtr       PDESC  <3FFH,0>        ; 实方式下,中断表,0:0处。

    SP_VALUE   DW        ?
    SS_VALUE   DW        ?
    IMASKREGV  db        ?
    Mes1  DB       0DH,0AH, "PRESS ANY KEY TO EXIT!"
    Mes1Len=$-Mes1
    
RDataSeg  ends    
;-------------------------------------------------------
;实方式下的代码段
RCodeSeg segment para use16
         assume cs:RCodeSeg,ds:RDataSeg
Start:
              MOV       AX,RDataSeg
              MOV       DS,AX
              mov       es,ax

              MOV       AH,0      ;清屏
              MOV       AL,03H
              INT       10H

              cld
              PUSH      DS
              CALL      INIT_GDT               ; 初始化全局描述符表GDT
          ;    CALL      INIT_IDT               ; 初始化中断描述符表IDT

              POP       DS

              MOV       SP_VALUE,SP
              MOV       SS_VALUE,SS
           ;   SIDT      QWORD PTR RealIdtr    ;为了回到实方式后,恢复原IDTR之内容,先保存IDTR
              in        al,21h
              mov       IMASKREGV,al
              
              LGDT      QWORD PTR V_GDTR      ; 装载GDTR 
              cli
           ;   LIDT      V_Idtr           ;装载中断描述符表寄存器IDTR

              CALL      EA20
              MOV       EAX,CR0
              OR        EAX,1
              MOV       CR0,EAX                          ; 启动保护方式
              JUMP16    TempCodeSel,<OFFSET Virtual>  ; 实方式下预取。
   Real:
              CALL      DA20
              MOV       AX,RDataSeg
              MOV       DS,AX
              LSS       SP,DWORD PTR SP_VALUE   ; 恢复实方式下的堆栈。

            ;  LIDT      RealIdtr
              mov       al,IMASKREGV
              out       21h,al
              sti
              MOV       AX,RDataSeg
              MOV       ES,AX
              LEA       BP,MES1
              MOV       DX,1700H
              MOV       BH,0
              MOV       CX,MES1Len
              MOV       AL,0
              MOV       BL,0D2H
              MOV       AH,13H
              INT       10H         ; 提示退出信息。
              MOV       AH,0
              INT       16H
              MOV       AH,6
              MOV       AL,0
              MOV       BH,7        ; f & b Color
              MOV       CX,0
              MOV       DX,184FH
              INT       10H         ; 清屏,恢复原屏幕。
              MOV       AX,4C00H
              INT       21H    
;----------------------------------------------------------------------------

INIT_GDT proc near
   push ds
ASSUME    DS:GdtSeg
   mov ax,GdtSeg
   mov ds,ax
   mov cx,GDTNUM
   lea si,effgdt
Inittg:
   mov ax,[si].BASEL
   MOV BX,16
   MUL BX
   mov [si].BASEL,ax
   mov [si].BASEM,dl
   mov [si].BASEH,dh
   add si,size DESC
   loop Inittg
   ASSUME    DS:RDataSeg
   pop ds

   mov bx,16
   mov ax,GdtSeg
   mul bx
   mov word ptr V_GDTR.BASE,ax
   mov word ptr V_GDTR.BASE+2,dx
   ret
INIT_GDT endp
;----------------

;INIT_LDT proc near
;Inittg_ldt:
;   mov ax,fs:[si].BASEL
;    MOV BX,16
;   MUL BX
;   mov fs:[si].BASEL,ax
;   mov fs:[si].BASEM,dl
;   mov fs:[si].BASEH,dh
;   add si,size desc
;   loop Inittg_ldt
;   ret
;INIT_LDT  endp

;-------------------
;  INIT_IDT proc
;    mov bx,16
;    mov ax,IdtSeg
;    mul bx
;    mov word ptr V_IDTR.BASE,AX
;    mov word ptr V_IDTR.BASE+2,DX
;    RET
; INIT_IDT  ENDP

;----------------
EA20 proc                    ; 打开A20。
   push ax
   in al,92h
   or al,2
   out 92h,al
   pop ax
   ret
EA20 endp

DA20 proc   ; 关闭A20。
   push ax
   in al,92h
   and al,0fdh
   out 92h,al
   pop ax
   ret
DA20 endp
 
 
RCodeSeg   ends
           end Start



  

   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -