📄 code16.asm
字号:
CALL MAKE_DESC
MOV SI,SEL_TSS1
MOV AH,RW_DATA
CALL MAKE_DESC
;psp
MOVZX EBX,PSP
SHL EBX,4
MOV ECX,255
MOV AH,RW_DATA
MOV AL,1
MOV SI,SEL_PSP
CALL MAKE_DESC
;Environment segment
PUSH ES
MOV ES,PSP
XOR EBX,EBX
MOV BX,ES:[2CH]
MOV AX,BX
SHL EBX,4
DEC AX
MOV ES,AX
XOR ECX,ECX
MOV CX,ES:[3]
SHL ECX,4
DEC ECX ;get limit form arena header
MOV SI,SEL_ENV
POP ES
MOV AL,1
MOV AH,RW_DATA
CALL MAKE_DESC ;make environment segment
;turn on A20
;MOV AL,1
;CALL SETA20
;no interrupts until prot mode
CLI
MOV SSEGSAV,SS
;save sp for triumphant return to r/m
MOV SOFFSAV,SP
SIDT IDTSAV
LIDT XZRO ;save and load IDT
XOR EBX,EBX
MOV BX,GDTSEG
SHL EBX,4
ADD EBX,OFFSET GDT
MOV TEMD,EBX
LGDT TEMP ;set up GDT
MOV EAX,CR0
OR EAX,1 ;switch to prot model
MOV CR0,EAX
;jump to load CS and filush prefetch
JMPABS SEL_CODE16,PROT1
PROT1: ;go!
OPSIZ
JMPABS32 SEL_CODE32,SEG32ENT ;see program PROT.ASM
;****************************************************************************
;Jump here to return to real mode DOS. *
;if desired AL can be set to a DOS exit code *
;****************************************************************************
BACK16 LABEL FAR
MOV BL,AL
CLI ;save exit code
;turn off debug (just in case)
XOR EAX,EAX
MOV DR7,EAX
;restore stack
LSS ESP,FWORD PTR CS:LOAD16
MOV AX,SEL_RDATA
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV EAX,CR0
;return to real mode
AND EAX,07FFFFFF2H
MOV CR0,EAX
;jump to load CS and clear prefetch
JMPABS CSEG,NEXTREAL
NEXTREAL LABEL FAR
MOV AX,CS
MOV DS,AX
LIDT IDTSAV ;restore old IDT 0(3ff)
;clean up to go back to DOS
LSS SP,DWORD PTR SOFFSAV
STI ;resume interrupt handling
;turn a20 back off
XOR AL,AL
CALL SETA20
MOV AH,4CH ;blow this joint!
MOV AL,BL ;get return code
INT 21H ;return to the planet of MSDOS
PM2REAL LABEL FAR
CLI ;save exit code
;turn off debug (just in case)
XOR EAX,EAX
MOV DR7,EAX
;restore stack
LSS ESP,FWORD PTR CS:LOAD16
MOV AX,SEL_RDATA
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV EAX,CR0
;return to real mode
AND EAX,07FFFFFF2H
MOV CR0,EAX
;jump to load CS and clear prefetch
JMPABS CSEG,NEXTREAL2
NEXTREAL2 LABEL FAR
MOV AX,CS
MOV DS,AX
LIDT IDTSAV ;restore old IDT 0(3ff)
;clean up to go back to DOS
LSS SP,DWORD PTR SOFFSAV
STI ;resume interrupt handling
;turn a20 back off
XOR AL,AL
CALL SETA20
MOV AX,WORD PTR CS:_RTCSIP[4] ;OLD FLAG
PUSH AX
POPF
MOV AX,WORD PTR CS:_RTCSIP[6] ;OLD ES
MOV ES,AX
MOV AX,WORD PTR CS:_RTCSIP[8] ;OLD DS
MOV DS,AX
MOV AX,WORD PTR CS:_RTCSIP[0AH] ;OLD SS
MOV SS,AX
MOV AX,WORD PTR CS:_RTCSIP[0CH] ;OLD BP
MOV BP,AX
MOV AX,WORD PTR CS:_RTCSIP[0EH] ;OLD SP
MOV SP,AX
MOV DI,WORD PTR CS:_RTCSIP[10H] ;DI
MOV SI,WORD PTR CS:_RTCSIP[12H] ;SI
MOV DX,WORD PTR CS:_RTCSIP[14H] ;DX
MOV CX,WORD PTR CS:_RTCSIP[16H] ;CX
MOV BX,WORD PTR CS:_RTCSIP[18H] ;BX
MOV AX,WORD PTR CS:_RTCSIP[1AH] ;AX
JMP DWORD PTR CS:_RTCSIP
START ENDP
;****************************************************************************
;Routine to control A20 line *
;AL=1 to turn A20 on (enable) *
;AL=0 to turn A20 off (disable) *
;returns ZF=1 if error; AX destroyed (and maybe CX) *
;****************************************************************************
SETA20 PROC NEAR
ASSUME CS:CSEG,DS:CSEG
CMP PS2,0
JZ SHORT NOTPS2A20
MOV AH,AL
OR AL,AL
IN AL,92H
JZ SHORT PS2OFF
OR AL,2
JMP SHORT PS2SET
PS2OFF: AND AL,0FDH
PS2SET: OUT 92H,AL
XOR CX,CX
PS2WAIT: IN AL,92H
SHR AL,1
CMP AL,AH
JZ SHORT PS2OUT
DEC CX
JNZ PS2WAIT
RET
PS2OUT: OR AL,1
RET
NOTPS2A20:
CMP PC386,0
JNZ SHORT A20IBPC
PUSH CX
MOV AH,0DFH ;A20 On
OR AL,AL
JNZ SHORT A20WAIT1
MOV AH,0DDH ;A20 Off
A20WAIT1:
CALL KEYWAIT
JZ SHORT A20ERR
MOV AL,0D1H
OUT 64H,AL
CALL KEYWAIT
JZ SHORT A20ERR
MOV AL,AH
OUT 60H,AL
CALL KEYWAIT
JZ SHORT A20ERR
MOV AL,0FFH
OUT 64H,AL
CALL KEYWAIT
A20ERR: POP CX
RET
;A20 set for inboard PC
A20IBPC:
OR AL,AL
MOV AL,0DFH
JNZ SHORT A20SET
MOV AL,0DDH
A20SET: OUT 60H,AL
OR AL,AL ;make sure ZF is clear for
RET
SETA20 ENDP
;****************************************************************************
;wait for keyboard controller ready, returns ZF=1, if timeout *
;destroys CX and AL *
;****************************************************************************
KEYWAIT PROC NEAR
XOR CX,CX ;maximum time out
KWAITLP:
DEC CX
JZ SHORT KEYEXIT
IN AL,64H
AND AL,2
JNZ KWAITLP
KEYEXIT: OR CX,CX
RET
KEYWAIT ENDP
;****************************************************************************
;This routine makes a descriptior *
;ebx=base *
;ecx=limit in bytes *
;es:edx=GDT address *
;al=size (0=16bit 1=32bit) *
;ah=AR byte *
;SI=descriptor (T1 & DPL not important!) *
;Auto sets and calculates G and limit *
;****************************************************************************
MAKE_DESC PROC NEAR
PUSHAD
MOVZX ESI,SI
SHR SI,3
;shift size to right bit position
SHL AL,6
CMP ECX,0FFFFFH ;see if you need to set G bit
JBE SHORT OKLIMR
SHR ECX,12 ;div by 4096
OR AL,80H ;set G bit
OKLIMR: 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
POPAD
RET
MAKE_DESC ENDP
;****************************************************************************
;* return to VM86 MODE *
;****************************************************************************
_TSR PROC FAR
;turn a20 back off
XOR AL,AL
CALL SETA20
MOV DX,09000H
INT 27H
RETF
_TSR ENDP
GETPARA PROC NEAR
PUSH BX
MOV BX,0
LOOPSPACE:
MOV AL,[BX+81H]
CMP AL,0DH
JZ NOPARA
CMP AL,20H
JNZ SKIPSPACE
INC BX
JMP LOOPSPACE
SKIPSPACE:
MOV AL,[BX+81H]
CMP AL,'/'
JZ CORRECTPARA
CMP AL,'-'
JZ CORRECTPARA
JMP NOTCORRECTPARA
NOPARA:
MOV AL,0
JMP EXITPARA
CORRECTPARA:
INC BX
MOV AL,[BX+81H]
OR AL,20H
CMP AL,'a'
JZ PARA1
CMP AL,'w'
JZ PARA2
CMP AL,'u'
JZ PARA3
CMP AL,'h'
JZ PARA4
CMP AL,'r'
JZ PARA5
JMP NOTCORRECTPARA
PARA1:
MOV EDX,0
NEXTNUMBER:
MOV AL,[BX+82H]
CMP AL,30H
JB NUMBEROVER
CMP AL,39H
JA NUMBEROVER
SUB AL,30H
MOV AH,0
MOVZX EAX,AX
SHL EDX,1
MOV ECX,EDX
SHL EDX,2
ADD EDX,ECX
ADD EDX,EAX
INC BX
JMP NEXTNUMBER
NUMBEROVER:
CMP EDX,0
JZ NOTSETEXT
SHL EDX,10
PUSH ES
MOV AX,SEG PORTDATAADDR
MOV ES,AX
MOVZX EAX,CS:_EXTSIZE
SHL EAX,10
SUB EAX,EDX
ADD EAX,100000H
MOV ES:PORTDATAADDR,EAX
ADD EAX,2
MOV ES:CURBLOCKADDR,EAX
POP ES
CMP EAX,100000H
JB NOTCORRECTPARA
NOTSETEXT:
MOV AL,1
JMP EXITPARA
PARA2:
MOV AL,2
JMP EXITPARA
PARA3:
MOV AL,3
JMP EXITPARA
PARA4:
MOV AL,4
JMP EXITPARA
PARA5:
MOV AL,5
JMP EXITPARA
NOTCORRECTPARA:
MOV DX,OFFSET NOTCORRECT
CALL SHOWSTRING
MOV AL,0FFH
EXITPARA:
POP BX
RET
GETPARA ENDP
HELPUSER PROC NEAR
PUSH DS
PUSH CS
POP DS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -