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

📄 pmstart8.asm

📁 保护模式下编程。通过陷阱门INT 0FEh进行字符串输出。通过任务状态段TSS进行任务切换
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	            mov al,byte ptr [si]
	            mov dx,0c408h               ;自8255A的口输出
	            out dx,al
              mov al,byte ptr bz           ;使相应的数码管亮
	            mov dx,0c409h
	            out dx,al
	
	            push cx                      ;延时,控制七段数码管相临两个数字显示之间的间隔
              mov cx,3     
delay11:      push cx
              mov cx,0ffffh
delay12:      loop delay12               
              pop  cx
              loop delay11
	            pop cx
	
              mov al,0                     ;数码管清零,防止前后两次显示的数字重叠
              mov dx,0c409h
              out dx,al
	
	            mov bh,byte ptr bz
	            shr bh,1
	            jnz lll
	            loop loop2                  ;循环延时
	            mov  ax,word ptr [di]
	            cmp  ah,09
	            jnz  set
              cmp  al,09
	            jnz  set
              mov  ax,0000
              mov  [di],al
	            mov  [di+1],ah
	            jmp  loop1
	
set:          mov dx,0c40ah                ;读8255C口
              in  al,dx
	            test al,08h
	            jne   returnb              ;K3=1返回SysCodeSeg
	            mov  ax,word ptr [di]
	            inc  al
	            aaa
	            mov [di],al                 ;al为十位
	            mov [di+1],ah               ;ah中为个位
	            jmp loop1            
returnb:      pop gs
              pop fs
              pop es
              pop ds
              popad   
              JUMP16 SysTssSel,0
              jmp  taskb
TaskBCodeLen=$
TaskBCodeSeg ends 
;-----------------------------------------------------------
;主任务状态段
SysTssSeg     segment para use16
SysTaskSS     TASKSS  < >
              db  0ffh             
SysTssLen=$
SysTssSeg   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! ',0
inputpin   db    '     If K0=1, return to real mode.      '
           db    '  If K1=1, go to TaskA.                 '
           db    '     If K2=1, go to TaskB,              '
           db    '  If K3=1, back from TaskA or TaskB.    ',0
endpm      db    '     Exit the protected mode! ' ,0 
backapm    db    '     Back from TaskA!         ',0
backbpm    db    '     Back from TaskB!         ',0
SysDataSeg ends
;--------------------
;主任务代码段
SysCodeSeg  segment para use16
            assume cs:SysCodeSeg,ds:SysDataSeg
do_pm:  mov ax,SysLdtSel
        lldt ax
        mov ax,SysStack0Sel     ;;;;;;;;;;;;;;
        mov ss,ax
        mov sp,offset SysStack0Len     ;;;;;;;;;;;;;;;
        mov ax,ToSysTssSel
        mov gs,ax                     ;把主任务LDT选择子填入TSS
        mov WORD PTR gs:SysTaskSS.TRLDT,SysLdtSel
        mov ax,SysTssSel
        ltr ax
        mov ax,SysDataSel
        mov ds,ax
        mov fs,ax
        mov gs,ax
        mov ax,VideoSel
        mov es,ax

        lea si,hipm             ;输出字符串,提示已经进入保护模式
        mov di,160*1
        INT 0FEh  
        lea si,inputpin
        mov di,160*3
        INT 0FEh

        mov dx,0c40bh               ;设置8255控制字
        mov al,89h
        out dx,al
testkey:         
        mov dx,0c40ah               ;读8255C口
        in  al,dx
        test al,01h
        jne  exit                   ;K0=1则转exit
        test al,02h        
        jne  totaska                ;K1=1则转TaskA
        test al,04h
        jne  totaskb                ;K2=1则转TaskB
        jmp testkey
       
exit:   lea si,endpm
        mov di,160*11
        INT 0FEh
        JUMP16    TempCodeSel,<OFFSET ToReal>

totaska:JUMP16 TaskATssSel,0
        clts
        lea si,backapm
        mov di,160*7
        INT 0FEh
        jmp testkey 
        
totaskb: JUMP16 TaskBTssSel,0
         clts 
         lea si,backbpm
         mov di,160*9
         INT 0FEh
         jmp testkey                    
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
; 初始化全局描述符表GDT              
              CALL      INIT_GDT  
; 初始化中断描述符表IDT                           
              CALL      INIT_IDT               
              
              mov     ax,SysLdtSeg
              mov     fs,ax
              mov     cx,SysLdtNum
              mov     si,OFFSET syldt
              CALL    INIT_LDT
              
              mov     ax,TaskALdtSeg
              mov     fs,ax
              mov     cx,TaskALdtNum
              mov     si,OFFSET taldt
              CALL    INIT_LDT
              
              mov     ax,TaskBLdtSeg
              mov     fs,ax
              mov     cx,TaskBLdtNum
              mov     si,OFFSET tbldt
              CALL    INIT_LDT
              
              POP       DS

              MOV       SP_VALUE,SP
              MOV       SS_VALUE,SS
;为了回到实方式后,恢复原IDTR之内容,先保存IDTR              
              SIDT      QWORD PTR RealIdtr    
              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 + -