📄 prot.asm
字号:
;*****************************************************************************
;* *
;* PROT - A softdog killer *
;* Copyright (C) 1996, by Li Wen_xian *
;* All rights reserved *
;* *
;* *
;* PROT.ASM - the main routines and protected mode support. *
;* STACKS.ASM - stack segments *
;* GDT.ASM - Global descriptor table. *
;* INT386.ASM - protected mode interrupt handlers. *
;* TSS.ASM - Task state segments. *
;* CODE16.ASM - 16 bit DOS code (entry/exit) *
;* EQUMAC.INC - Equates and macros. *
;* EXTERNAL.INC - External definitions. *
;* CANE.INC - User's external definitions. *
;* TSS.INC - TSS structure. *
;* PROT.MAK - Makefile *
;* PROTASM.BAT - Compile driver. *
;* _PROTASM.BAT - Used by PROTASM.BAT *
;* *
;* This file is: PROT.ASM, the main protected mode code. *
;* *
;*****************************************************************************
;equates and macros
INCLUDE EQUMAC.INC
PROT_FILE EQU 1
INCLUDE EXTERNAL.INC
PUBLIC CRITSI, CRITBP, CRITDI, CRITAX
PUBLIC CRITICAL
PUBLIC BREAKKEY, BREAK_HANDLE, BRK_OFF, BRK_SEG, _PSP
PUBLIC INTSP, _PC386
PUBLIC STO1, STO2, STO3, STO4, MULTI, MLOCK
PUBLIC DUMP_OFF, DUMP_CNT, DUMP_SEG, SAV_DS
PUBLIC SAV_ES, SAV_GS, SAV_FS, CURSOR, COLOR
PUBLIC EXEFLAG
;this is required to find out how large PROT is
ZZZGROUP GROUP ZZZSEG
;*****************************************************************************
; 32 bit data segment
DAT32 SEGMENT
DAT32BEG EQU $
;cane is for emulation or analyse
EXEFLAG DB 0
;32 bit stack values
SLOAD DD OFFSET SSEG321
SSLD DW SEL_STACK
;This location will hold the address for the PMODE IDT
NEWIDT EQU THIS FWORD
DW IDTLEN
IDTB DD 0 ;filled in at runtime
; PSP segment address
_PSP DW 0
;flag set to 1 if INTEL INBOARD 386/PC
_PC386 DB 0
;C programs SP
;nultitasking variables
;multitasking on
MULTI DB 0
;multitasking lock counter
MLOCK DW 0
;video variables for the OUCH and related routines
CURSOR DD 0 ;cursor location
COLOR DB 7 ;display color
;temp vars for some non reentrant interrupt routines
STO1 DD 0
STO2 DD 0
STO3 DD 0
STO4 DD 0
SAV_DS DD 0
SAV_ES DD 0
SAV_GS DD 0
SAV_FS DD 0
;Enables comditional breakpoints
BPON DB 0
;Debug Dump variables
DUMP_SEG DW 0 ;if zero don't dump memory
DUMP_OFF DD 0 ;Offset to start at
DUMP_CNT DD 0 ; # of bytes to dump
;Break & critical error handler variables
BREAKKEY DB 0 ;break key occurred
CRITICAL DB 0 ;critical error occurred
CRITAX DW 0 ;critical error ax
CRITDI DW 0 ;critical error di
CRITBP DW 0 ;critical error bp
CRITSI DW 0 ;critical error si
;Address of user's break handler
BREAK_HANDLE EQU THIS FWORD
BRK_OFF DD 0
BRK_SEG DW 0
;Message for default critical error handler
CRITMSG DB 'A critical error has occurred.',13,10
DB '<A>bort, <R>etry, <F>ail:?$'
;here is where vm86 int's stack up p10 esp's
INTSP DD $+PVSTACK+4
DB PVSTACK DUP (0)
;storage for the original PIC interrupt mask registers
INTMASK DB 0
INTMASKAT DB 0
DAT32END EQU $
DAT32 ENDS
;****************************************************************
;Begin 32 bit code segment
SEG32 SEGMENT
ASSUME CS:SEG32, DS:DAT32
PUBLIC SEG32ENT, SEG32LEN
PCODE PROC
SEG32BEG EQU $
;Start of protected mode code
;We jump here from inside CODE16.INC
SEG32ENT:
MOV AX,SEL_DATA ;1st order of business:
MOV DS,AX ;load up segment registers
LSS ESP,FWORD PTR SLOAD
MOV AX, SEL_VIDEO
MOV ES,AX
MOV AX,SEL_DATA0
MOV FS,AX
MOV AX,SEL_GDT
MOV GS,AX
;set up IDT
CALL32S MAKIDT
STI ;enable interrupts
;*** start user code with TSS (req'd for vm86 op's etc.)
MOV AX,TSS0
LTR AX
JMPABS32 TSS1,0
PCODE ENDP
;*** 32 bit support routines
;This routine creates the required IDT
;This is only a subroutine to keep from cluttering up
;the main code, since you aren't likely to call it again.
;Assumes that all ISR routines are of fixed length and in
;sequence. Of course, after makidt has built the table, you
;can still replace individual INT gates with your own gates
;(see make_gate)
MAKIDT PROC NEAR
PUSH ES
MOV AX, IDTABLE
MOVZX EAX,AX
SHL EAX,4
ADD EAX,OFFSET IDTBEG
MOV IDTB,EAX
MOV AX,SEL_IDT
MOV ES,AX
XOR AL,AL
;Make all interrupt gates DPL=3
MOV AH,INTR_GATE OR DPL3
MOV CX,SEL_ICODE
MOV EDX, OFFSET IDTBEG
XOR SI,SI
MOV EBX,OFFSET INT0
IDTLOOP:
CALL32F SEL_CODE32,MAKE_GATE
ADD EBX,INTLEN
ADD SI,8
;Loop form max # of interrupts
CMP SI,(TOPINT+1)*8
JB SHORT IDTLOOP
LIDT NEWIDT
POP ES
RET
MAKIDT ENDP
;This routine is just like the real mode make_desc
;EBX = base ECX=limit AH=ARB AL=0 or 1 for 16 or 32 bit
;SI = selector (T1&RPL ignored) and ES:EDX is the table base address
MAKE_SEG PROC FAR
GOMAKE_SEG:
PUSH ESI
PUSH EAX
PUSH ECX
MOVZX ESI,SI
SHR SI,3 ;adjust to slot #
;shift size to right bt position
SHL AL,6
CMP ECX, 0FFFFFH ;see if you need to set G bit
JLE SHORT OKLIM
SHR ECX,12 ;div by 4096
OR AL,80H ;set G bit
OKLIM: MOV ES:[EDX+ESI*8],CX
SHR ECX,16
OR CL,AL
MOV ES:[EDX+ESI*8+6],CL
MOV ES:[EDX+ESI*8+2],BX
SHR EBX,16
MOV ES:[EDX+ESI*8+4],BL
MOV ES:[EDX+ESI*8+5],AH
MOV ES:[EDX+ESI*8+7],BH
POP ECX
POP EAX
POP ESI
RET
MAKE_SEG ENDP
;This routine make gates
;AL=WC if applicable
;AH=ARB EBX=offset CX=selector ES: EDX=table base
;SI= selector (T1 & RPL ignored)
MAKE_GATE PROC FAR
GOMAKE_GATE:
PUSH ESI
PUSH EBX
SHR SI,3
MOVZX ESI,SI
MOV ES:[EDX+ESI*8],BX
MOV ES:[EDX+ESI*8+2],CX
MOV ES:[EDX+ESI*8+4],AX
SHR EBX,16
MOV ES:[EDX+ESI*8+6],BX
POP EBX
POP ESI
RET
MAKE_GATE ENDP
;Directly clear page 0 of the screen
CLS PROC FAR
PUSHFD
PUSH DS
PUSH ES
PUSH EDI
PUSH ECX
PUSH EAX
MOV CX,SEL_VIDEO
MOV ES,CX
MOV CX,SEL_DATA
MOV DS,CX
CLD
MOV EDI,0
MOV ECX,2000
MOV AX,0720H
REP STOSW
XOR ECX,ECX
MOV CURSOR,ECX
POP EAX
POP ECX
POP EDI
POP ES
POP DS
POPFD
RET
CLS ENDP
;Outputs message to screen
;ASCIIZ pointer in ds:ebx - modifies ebx
MESSOUT PROC FAR
PUSH EAX
NXT: MOV AL,[EBX]
INC EBX
OR AL,AL
JNZ SHORT SKIP
POP EAX
RET
SKIP:
CALL32F SEL_CODE32,OUCH
JMP SHORT NXT
MESSOUT ENDP
;Performs CR/LF sequence to screen using OUCH
CRLF PROC FAR
PUSH EAX
MOV AL,13
CALL32F SEL_CODE32,OUCH
MOV AL,10
CALL32F SEL_CODE32,OUCH
POP EAX
RET
CRLF ENDP
;Character and digit output routines
;hexout4 - print longword in EAX in hex
;hexout2 - print word in AX in hex
;hexout - print byte in AL in hex
;ouch - print ASCII character in AL
OUTPUT PROC FAR
;print longword in eax
HEXOUT4 LABEL FAR
PUSH EAX
SHR EAX,16
CALL32F SEL_CODE32,HEXOUT2
POP EAX
;print word in ax
HEXOUT2 LABEL FAR
PUSH EAX
MOV AL,AH
CALL32F SEL_CODE32,HEXOUT
POP EAX
;print a hex byte in al
HEXOUT LABEL FAR
MOV BL,AL
AND AX,0F0H
SHL AX,4
MOV AL,BL
AND AL,0FH
ADD AX,'00'
MOV BL,AL
MOV AL,AH
CALL32F SEL_CODE32,HEXIDIG
MOV AL,BL
HEXIDIG: CMP AL,'9'
JBE SHORT HIDIG
ADD AL,'A'-'0'-0AH
HIDIG:
OUCH LABEL FAR
PUSH EDI
PUSH EAX
PUSH DS
PUSH ES
PUSH ECX
MOV CX,SEL_VIDEO
MOV ES,CX
MOV CX,SEL_DATA
MOV DS,CX
POP ECX
MOV AH,COLOR
MOV EDI,CURSOR
CMP EDI,2000 ;rolling off the screen?
JB SHORT NOSCROLL
;scroll screen if required
PUSH DS
PUSH ES
POP DS
PUSH ESI
PUSH ECX
PUSH EDI
CLD
MOV ECX,960
XOR EDI,EDI
MOV ESI,160
REP MOVSD
POP EDI
SUB EDI,80
POP ECX
POP ESI
POP DS
NOSCROLL: CMP AL,0DH
JZ SHORT CR
CMP AL,0AH
JZ SHORT LF
;write to screen
MOV ES:[EDI*2],AX
CALL32F SEL_CODE32,GOUT
INC EDI
JMP SHORT OUCHD
CR: PUSH EDX
PUSH ECX
MOV EAX,EDI
XOR EDX,EDX
MOV ECX,80
DIV ECX
SUB EDI,EDX
POP ECX
POP EDX
JMP SHORT OUCHD
LF: ADD EDI,50H
OUCHD: MOV CURSOR,EDI ;update cursor
POP ES
POP DS
POP EAX
POP EDI
RET
OUTPUT ENDP
GOUT PROC FAR
PUSHAD
PUSH ES
PUSH EAX
MOV AX,SEL_DATA0
MOV ES,AX
POP EAX
MOV ECX,0
MOV EDX,0
LOOP1:
CMP ECX,8
JAE NEXT1
PUSH EAX
PUSH EDI
MOV EBX,EAX
AND EBX,0FFH
SHL EBX,3
ADD EBX,ECX
MOV AL,ES:[0FFA6EH+EBX]
MOV EBX,EDX
LOOP2:
CMP EDI,0050H
JB NEXT2
SUB EDI,80
ADD EBX,800
JMP LOOP2
NEXT2:
ADD EBX,EDI
MOV ES:[0A0000H+EBX],AL
INC ECX
ADD EDX,80
POP EDI
POP EAX
JMP LOOP1
NEXT1:
POP ES
POPAD
RET
GOUT ENDP
PUBLIC OUCH,HEXOUT,HEXOUT2,HEXOUT4,CRLF,CLS
PUBLIC MESSOUT
PUBLIC MAKE_GATE, MAKE_SEG
;Default critical error handler
SEG32END EQU $
SEG32 ENDS
SEG32LEN EQU (SEG32END-SEG32BEG)-1
PUBLIC SEG32LEN
DAT32LEN EQU (DAT32END-DAT32BEG)-1
PUBLIC DAT32LEN
;segment to determine the last memory address
ZZZSEG SEGMENT
ZZZSEG ENDS
END ENTRY
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -