ýòîì ïðèìåðå, äëÿ ñðàâíåíèÿ, íàïèñàíû äâå,
ïðàêòè÷åñêè îäèíàêîâûå ïðîãðàììû. Ðàçíèöà ëèøü â òîì, ÷òî â îäíîé ñòðàíè÷íîå
ïðåîáðàçîâàíèå àäðåñîâ èñïîëüçóåòñÿ, â äðóãîé – íåò. Îáå ïðîãðàììû çàïîëíÿþò
îáëàñòü âèäåîáóôåðà îäèíàêîâûìè ÷èñëàìè. Íî â ñâÿçè ñ òåì, ÷òî òàáëèöà ñòðàíèö íàñòðàèâàåòñÿ íå íà ïîëíîå
ñîîòâåòñòâèå ëèíåéíûõ àäðåñîâ
ôèçè÷åñêèì, êàðòèíêè íà ýêðàíå áóäóò ðàçëè÷íûìè.
Íèæå ïðèâåäåíû èñõîäíûå òåêñòû ïðîãðàìì (ñíà÷àëà ãëàâíûå ìîäóëè, à çà
íèìè «âêëþ÷àåìûå» *.inc
– ìîäóëè, îáùèå äëÿ îáåèõ ïðîãðàìì).
paging.asm (Èñïîëüçóåòñÿ
ñòðàíè÷íîå ïðåîáðàçîâàíèå)
.MODEL SMALL
INCLUDE MACROSES.INC
STACK_SIZE EQU
1000H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 16-BIT
REAL/PROTECTED MODE CODE SEGMENT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.8086
CODE16 SEGMENT PARA 'CODE' USE16
CODE16_BEGIN =
$
ASSUME CS:CODE16,DS:DATA16,ES:DATA16
MAIN PROC
MOV AX, DATA16
MOV DS, AX
MOV ES, AX
LEA DX, MSG_STARTUP
MOV AH, 9
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;
;; DETECTING HARDWARE
;;
;;;;;;;;;;;;;;;;;;;;;;;;
CALL DETECT
.386P
LEA DX, MSG_EXT_MEM
MOV AH, 9
INT 21H
MOV EAX, [EXT_MEMORY]
SHR EAX, 10
LEA DI, WRITE_BUF
CALL DEC2STR
MOV DWORD PTR [WRITE_BUF+10], 240A0DH
LEA DX, WRITE_BUF
MOV AH, 9
INT 21H
MOV EAX, 5
CALL
delayRTC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; WE'RE GOING TO
ENTER THE PROTECTED MODE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CALL SETUP_GDT
@ENABLE_A20 ; ENABLE A20 LINE
IN
AL, PORT_INT_MASK_M
MOV
[INT_MASK_M], AL ;
SAVE MASK OF HARDWARE INTS AT MASTER CNTRLR
IN
AL, PORT_INT_MASK_S
MOV
[INT_MASK_S], AL ;
SAVE MASK OF HARDWARE INTS AT SLAVE CNTRLR
CLI ; DISABLE
MASKABLE INTS
@DISABLE_NMI ; DISABLE
NON-MASKABLE INTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COPYING PAGE
TABLE TO THE 110000H ADDRESS ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV
BX, DS
MOVZX
EBX, BX
SHL
EBX, 4
LEA
SI, PAGETAB
MOVZX
ESI, SI
ADD
ESI, EBX
MOV
EDI, 110000H ;
1MB+64KB = PAGE TABLE
MOV
CX, 1024*4 ;
1024 PAGE TABLE ENTRIES (4MB)
CALL
COPY_BLOCK
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COPYING PAGE
DIRECTORY TO THE 120000H ADDRESS ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LEA
SI, PAGEDIR
MOVZX
ESI, SI
ADD
ESI, EBX
MOV
EDI, 120000H ;
1MB+128KB = PAGE DIRECTORY
MOV
CX, 4
CALL
COPY_BLOCK ;
PAGE DIR IS ALSO A PAGE TAB
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LOADING CR3
WITH PAGE DIRECTORY ADDRESS (120000H) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV
EDI, CR3
AND
EDI, 0FFFH
OR
EDI, 120000H
MOV
CR3, EDI ;
CR3 = ^PAGE DIRECTORY
MOV
AX, 13H
INT
10H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; HERE GOES THE
SWITCHING ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LGDT
[GDTR] ;
LOAD GDTR
MOV
EAX, CR0
AND
EAX, 01111111111111111111111111110000B
; THIS DOES NOT
ENABLE PAGING AND 16 COLORED BARS WILL BE DRAWN
; IN THIS ORDER
(TOP TO DOWN): BLACK, BLUE, ... YELLOW, WHITE
; OR
EAX, 00000000000000000000000000000001B
; THIS ENABLES
PAGING AND 16 COLORED BARS WILL BE DRAWN
; IN THIS ORDER
(TOP TO DOWN): WHITE, YELLOW, ... BLUE, BLACK
OR
EAX, 10000000000000000000000000000001B
MOV
CR0, EAX ; SET UP PROTECTED MODE
; THIS "JMP
$" SHOULD HANG COMPUTER IF SET UP OF PMODE IS SUCCESSFUL
; JMP $
@JUMP ; OVERLOAD
CODE SELECTOR
MOV
AX, DS16_SEL
MOV
DS, AX ; LOAD DS WITH DATA SELECTOR
MOV
ES, AX ;
LOAD ES WITH DATA SELECTOR
MOV
AX, SS16_SEL
MOV
SS, AX ;
LOAD SS WITH STACK SELECTOR
MOVZX
ESP, SP
MOV [ESP32], ESP
XOR
AX, AX
MOV
FS, AX ;
LOAD FS WITH 0
MOV
GS, AX ;
LOAD GS WITH 0
LLDT
AX ;
LOAD LDTR WITH 0
@SET_INT_CTRLR 20H, 28H ; REINITIALISE MASTER &
SLAVE INT CONTROLLERS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PMODE IS SET
UP ;;
;; HERE MAY BE ANY OWN PMODE
CODE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PUSH
ES
MOV
AX, GRAPH_SEL
MOV
ES, AX
XOR
DI, DI
MOV
DX, 0
CLD
START_GFX_CYCLE:
MOV
AL, DL
MOV
CX, 4096
REP
STOSB
INC
DX
CMP
DX, 16
JC
START_GFX_CYCLE
POP
ES
MOV EAX, 5
CALL delayRTC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; WE'RE GOING TO
GET BACK TO THE REAL MODE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
START_BACK_TO_16:
CLI ; DISABLE
MASKABLE INTS
@DISABLE_NMI ; DISABLE
NON-MASKABLE INTS
MOV
AX, DS16_SEL
MOV
DS, AX ;
SAFETY IS WHAT WE NEED!!!
MOV
ES, AX ;
SAFETY IS WHAT WE NEED!!!
MOV
AX, SS16_SEL
MOV
SS, AX
MOV
ESP, [ESP32]
INCLUDE SET_RM1.INC
MOV
AL, [INT_MASK_M]
OUT
PORT_INT_MASK_M, AL ;
RESTORE MASK OF HARDWARE INTS AT MASTER CNTRLR
MOV
AL, [INT_MASK_S]
OUT
PORT_INT_MASK_S, AL ;
RESTORE MASK OF HARDWARE INTS AT SLAVE CNTRLR
@ENABLE_NMI ; ENABLE
NON-MASKABLE INTS
STI ; ENABLE
MASKABLE INTS
@DISABLE_A20 ; DISABLE A20 LINE
MOV
AX, 3
INT
10H
LEA DX, MSG_CONTACT
MOV AH, 9
INT 21H
MOV AX, 4C00H
INT
21H
MAIN ENDP
delayRTC PROC NEAR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Input : eax =
number of seconds for delay ;;
;; Output: None,
registers are preserved ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PUSH EAX
PUSH EBX
PUSH ECX
MOV ECX, EAX
XOR AL, AL
OUT 70H, AL
JMP DRL1
DRL1:
IN AL, 71H
MOV BL, AL
DRLL:
XOR AL, AL
OUT 70H, AL
JMP DRL2
DRL2:
IN AL, 71H
CMP AL, BL
JE DRLL
MOV BL, AL
LOOP DRLL
POP ECX
POP EBX
POP EAX
RET
delayRTC ENDP
INCLUDE DETECT.INC
INCLUDE NUM2STR.INC
INCLUDE SETUPGDT.INC
INCLUDE CPYBLCK.INC
CODE16_SIZE =
$ - CODE16_BEGIN
CODE16 ENDS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COMMON
REAL/PROTECTED MODE DATA SEGMENT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DATA16 SEGMENT PARA 'DATA'
DATA16_BEGIN =
$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LAUNCH-TIME
ERROR MESSAGES ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MSG_STARTUP DB
"Example of paging stuff by Alexei A. Frounze (C)
2000",13,10,"$"
MSG_CONTACT DB
"Contact information:",13,10
DB
"E-mail :
alexfru@chat.ru",13,10
DB "Homepage:
http://alexfru.chat.ru",13,10
DB "Mirror :
http://members.xoom.com/alexfru",13,10,"$"
MSG_NEEDED_386 DB
"80386 OR BETTER PROCESSOR IS NEEDED.",13,10,"$"
MSG_NEEDED_RM DB
"PROCESSOR IS ALREADY IN PROTECTED MODE.",13,10
DB "PROBABLY WINDOWS OR EMM386.EXE IS
LOADED.",13,10
DB "LOAD PURE DOS IN REAL
MODE.",13,10,"$"
MSG_FOUND_HIMEM
DB "HIMEM.SYS IS INSTALLED.
DON'T LOAD IT PLEASE.",13,10,"$"
MSG_NEEDED_VGA DB
"VGA OR SVGA(VESA COMPATIBLE) VIDEO ADAPTER IS
NEEDED.",13,10,"$"
MSG_EXT_MEM DB
"MEMORY ABOVE 1MB+64KB FOUND (KB): $"
MSG_MEM_ERR DB
"NOT ENOUGH MEMORY!",13,10,"$"
;;;;;;;;;;;;;;;;;;;;;;
;; STRING
CONSTANTS ;;
;;;;;;;;;;;;;;;;;;;;;;
; HEXADECIMAL
TABLE FOR CONVERTING BCD TO TEXT
HEX_TAB DB
"0123456789ABCDEF"
; BUFFER FOR
CONVERTING DECIMAL AND HEX NUMBERS TO STRINGS
WRITE_BUF DB
16 DUP (0), 13, 10, "$"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; GLOBAL
DESCRIPTOR TABLE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDTR DF GDT_SIZE-1
GDT_BEGIN =
$
GDT LABEL WORD
GDT_0 S_DESC <0,0,0,0,0,0> ; 00
GDT_CS16 S_DESC
<CODE16_SIZE-1,,,ACS_CODE,0,>
; 08
GDT_DS16 S_DESC
<DATA16_SIZE-1,,,ACS_DATA,0,>
; 10
GDT_SS16 S_DESC <STACK_SIZE
-1,,,ACS_STACK,0,> ; 18
GDT_BIOS S_DESC
<SIZE_BIOS-1,LOW_BIOS,HIGH_BIOS,ACS_DATA+ACS_DPL_3,0,0> ; 20
GDT_TEXT S_DESC
<SIZE_TEXT-1,LOW_TEXT,HIGH_TEXT,ACS_DATA+ACS_DPL_3,0,0> ; 28
GDT_GRAPH S_DESC <SIZE_GRAPH-1,LOW_GRAPH,HIGH_GRAPH,ACS_DATA+ACS_DPL_3,0,0>;30
GDT_FLAT S_DESC
<0FFFFH,0,0,ACS_DATA,08FH,0> ; 4
GB SEGMENT ;)) ; 38
GDT_SIZE =
$ - GDT_BEGIN
GDT_SRC32 S_DESC <0FFFFH,,,ACS_DATA,0,> ; 40 (TEMPORARY)
GDT_DST32 S_DESC <0FFFFH,,,ACS_DATA,0,> ; 48 (TEMPORARY)
CS16_SEL =
GDT_CS16 - GDT_0
DS16_SEL =
GDT_DS16 - GDT_0
SS16_SEL =
GDT_SS16 - GDT_0
BIOS_SEL =
(GDT_BIOS - GDT_0) OR RPL_3
TEXT_SEL =
(GDT_TEXT - GDT_0) OR RPL_3
GRAPH_SEL =
(GDT_GRAPH - GDT_0) OR RPL_3
FLAT_SEL =
GDT_FLAT - GDT_0
SRC32_SEL =
GDT_SRC32 - GDT_0
DST32_SEL =
GDT_DST32 - GDT_0
;;;;;;;;;;;;;;;;
;; DUMMY IDTR ;;
;;;;;;;;;;;;;;;;
IDTR0 DF 0 ; USED FOR SWITCHING TO REAL
MODE
IDTR1 DF 3FFh
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; OTHER SYSTEM
VARIABLES ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ORIGINAL MASKS FOR
IRQS
INT_MASK_M DB
?
INT_MASK_S DB
?
; AMMOUNT OF THE
EXTENDED MEMORY ABOVE 1MB+64KB
EXT_MEMORY DD
?
; STACK POINTER
STORAGE
ESP32 DD ?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PAGE DIRECTORY
THAT IS COPIED TO THE 120000H ADDRESS ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PAGEDIR DD
110003H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PAGE TABLE THAT
IS COPIED TO THE 110000H ADDRESS ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PAGETAB LABEL
DWORD
N = 0
REPT
160
DD
N OR 3
N = N + 4096
ENDM
; N = 160*4096
; REPT
16
; DD
N OR 3
; N = N + 4096
; ENDM
N = (160+15)*4096 ; REVERSED ORDER OF PAGES IN THE VGA
BUFFER
REPT
16
DD
N OR 3
N = N - 4096
ENDM
N = (160+16)*4096
REPT
1024-(160+16)
DD
N OR 3
N = N + 4096
ENDM
DATA16_SIZE =
$ - DATA16_BEGIN
DATA16 ENDS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COMMON
REAL/PROTECTED MODE STACK SEGMENT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STACK16 SEGMENT
PARA STACK 'STACK'
DB STACK_SIZE DUP(?)
STACK16 ENDS
END MAIN
nopaging.asm
(Ñòðàíè÷íîå ïðåîáðàçîâàíèå íå èñïîëüçóåòñÿ)
.MODEL SMALL
INCLUDE MACROSES.INC
STACK_SIZE EQU
1000H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 16-BIT
REAL/PROTECTED MODE CODE SEGMENT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.8086
CODE16 SEGMENT PARA 'CODE' USE16
CODE16_BEGIN =
$
ASSUME CS:CODE16,DS:DATA16,ES:DATA16
MAIN PROC
MOV AX, DATA16
MOV DS, AX
MOV ES, AX
LEA DX, MSG_STARTUP
MOV AH, 9
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;
;; DETECTING
HARDWARE ;;
;;;;;;;;;;;;;;;;;;;;;;;;
CALL DETECT
.386P
LEA DX, MSG_EXT_MEM
MOV AH, 9
INT 21H
MOV EAX, [EXT_MEMORY]
SHR EAX, 10
LEA DI, WRITE_BUF
CALL DEC2STR
MOV DWORD PTR [WRITE_BUF+10], 240A0DH
LEA DX, WRITE_BUF
MOV AH, 9
INT 21H
MOV EAX, 5
CALL delayRTC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; WE'RE GOING TO
ENTER THE PROTECTED MODE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CALL SETUP_GDT
@ENABLE_A20 ; ENABLE A20 LINE
IN
AL, PORT_INT_MASK_M
MOV
[INT_MASK_M], AL ;
SAVE MASK OF HARDWARE INTS AT MASTER CNTRLR
IN
AL, PORT_INT_MASK_S
MOV
[INT_MASK_S], AL ;
SAVE MASK OF HARDWARE INTS AT SLAVE CNTRLR
CLI
; DISABLE MASKABLE INTS
@DISABLE_NMI ; DISABLE
NON-MASKABLE INTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COPYING PAGE
TABLE TO THE 110000H ADDRESS ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV
BX, DS
MOVZX
EBX, BX
SHL
EBX, 4
LEA
SI, PAGETAB
MOVZX
ESI, SI
ADD
ESI, EBX
MOV
EDI, 110000H ;
1MB+64KB = PAGE TABLE
MOV
CX, 1024*4 ;
1024 PAGE TABLE ENTRIES (4MB)
CALL
COPY_BLOCK
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COPYING PAGE
DIRECTORY TO THE 120000H ADDRESS ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LEA
SI, PAGEDIR
MOVZX
ESI, SI
ADD
ESI, EBX
MOV
EDI, 120000H ;
1MB+128KB = PAGE DIRECTORY
MOV
CX, 4
CALL
COPY_BLOCK ;
PAGE DIR IS ALSO A PAGE TAB
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LOADING CR3
WITH PAGE DIRECTORY ADDRESS (120000H) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV
EDI, CR3
AND
EDI, 0FFFH
OR
EDI, 120000H
MOV
CR3, EDI ;
CR3 = ^PAGE DIRECTORY
MOV
AX, 13H
INT
10H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; HERE GOES THE
SWITCHING ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LGDT
[GDTR] ;
LOAD GDTR
MOV
EAX, CR0
AND
EAX, 01111111111111111111111111110000B
; THIS DOES NOT
ENABLE PAGING AND 16 COLORED BARS WILL BE DRAWN
; IN THIS ORDER
(TOP TO DOWN): BLACK, BLUE, ... YELLOW, WHITE
OR
EAX, 00000000000000000000000000000001B
; THIS ENABLES
PAGING AND 16 COLORED BARS WILL BE DRAWN
; IN THIS ORDER
(TOP TO DOWN): WHITE, YELLOW, ... BLUE, BLACK
; OR
EAX, 10000000000000000000000000000001B
MOV
CR0, EAX ; SET UP PROTECTED MODE
; THIS "JMP
$" SHOULD HANG COMPUTER IF SET UP OF PMODE IS SUCCESSFUL
; JMP $
@JUMP ; OVERLOAD
CODE SELECTOR
MOV
AX, DS16_SEL
MOV
DS, AX ; LOAD DS WITH DATA SELECTOR
MOV
ES, AX ;
LOAD ES WITH DATA SELECTOR
MOV
AX, SS16_SEL
MOV
SS, AX ;
LOAD SS WITH STACK SELECTOR
MOVZX
ESP, SP
MOV [ESP32], ESP
XOR
AX, AX
MOV
FS, AX ;
LOAD FS WITH 0
MOV
GS, AX ;
LOAD GS WITH 0
LLDT
AX ;
LOAD LDTR WITH 0
@SET_INT_CTRLR 20H, 28H ; REINITIALISE MASTER &
SLAVE INT CONTROLLERS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PMODE IS SET
UP ;;
;; HERE MAY BE ANY OWN PMODE
CODE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PUSH
ES
MOV
AX, GRAPH_SEL
MOV
ES, AX
XOR
DI, DI
MOV
DX, 0
CLD
START_GFX_CYCLE:
MOV
AL, DL
MOV
CX, 4096
REP
STOSB
INC
DX
CMP
DX, 16
JC
START_GFX_CYCLE
POP
ES
MOV EAX, 5
CALL delayRTC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; WE'RE GOING TO
GET BACK TO THE REAL MODE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
START_BACK_TO_16:
CLI ; DISABLE
MASKABLE INTS
@DISABLE_NMI ; DISABLE
NON-MASKABLE INTS
MOV
AX, DS16_SEL
MOV
DS, AX ;
SAFETY IS WHAT WE NEED!!!
MOV
ES, AX ;
SAFETY IS WHAT WE NEED!!!
MOV
AX, SS16_SEL
MOV
SS, AX
MOV
ESP, [ESP32]
INCLUDE SET_RM1.INC
MOV
AL, [INT_MASK_M]
OUT
PORT_INT_MASK_M, AL ;
RESTORE MASK OF HARDWARE INTS AT MASTER CNTRLR
MOV
AL, [INT_MASK_S]
OUT
PORT_INT_MASK_S, AL ;
RESTORE MASK OF HARDWARE INTS AT SLAVE CNTRLR
@ENABLE_NMI ; ENABLE
NON-MASKABLE INTS
STI ; ENABLE
MASKABLE INTS
@DISABLE_A20 ; DISABLE A20 LINE
MOV
AX, 3
INT
10H
LEA DX, MSG_CONTACT
MOV AH, 9
INT 21H
MOV AX, 4C00H
INT 21H
MAIN ENDP
delayRTC PROC NEAR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Input : eax =
number of seconds for delay ;;
;; Output: None,
registers are preserved ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PUSH EAX
PUSH EBX
PUSH ECX
MOV ECX, EAX
XOR AL, AL
OUT 70H, AL
JMP DRL1
DRL1:
IN AL, 71H
MOV BL, AL
DRLL:
XOR AL, AL
OUT 70H, AL
JMP DRL2
DRL2:
IN AL, 71H
CMP AL, BL
JE DRLL
MOV BL, AL
LOOP DRLL
POP ECX
POP EBX
POP EAX
RET
delayRTC ENDP
INCLUDE DETECT.INC
INCLUDE NUM2STR.INC
INCLUDE SETUPGDT.INC
INCLUDE CPYBLCK.INC
CODE16_SIZE =
$ - CODE16_BEGIN
CODE16 ENDS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COMMON
REAL/PROTECTED MODE DATA SEGMENT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DATA16 SEGMENT PARA 'DATA'
DATA16_BEGIN =
$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LAUNCH-TIME
ERROR MESSAGES ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MSG_STARTUP DB
"Example of paging stuff by Alexei A. Frounze (C)
2000",13,10,"$"
MSG_CONTACT DB
"Contact information:",13,10
DB
"E-mail :
alexfru@chat.ru",13,10
DB "Homepage:
http://alexfru.chat.ru",13,10
DB "Mirror :
http://members.xoom.com/alexfru",13,10,"$"
MSG_NEEDED_386 DB
"80386 OR BETTER PROCESSOR IS NEEDED.",13,10,"$"
MSG_NEEDED_RM DB
"PROCESSOR IS ALREADY IN PROTECTED MODE.",13,10
DB "PROBABLY WINDOWS OR EMM386.EXE IS
LOADED.",13,10
DB "LOAD PURE DOS IN REAL
MODE.",13,10,"$"
MSG_FOUND_HIMEM
DB "HIMEM.SYS IS INSTALLED.
DON'T LOAD IT PLEASE.",13,10,"$"
MSG_NEEDED_VGA DB
"VGA OR SVGA(VESA COMPATIBLE) VIDEO ADAPTER IS
NEEDED.",13,10,"$"
MSG_EXT_MEM DB
"MEMORY ABOVE 1MB+64KB FOUND (KB): $"
MSG_MEM_ERR DB
"NOT ENOUGH MEMORY!",13,10,"$"
;;;;;;;;;;;;;;;;;;;;;;
;; STRING
CONSTANTS ;;
;;;;;;;;;;;;;;;;;;;;;;
; HEXADECIMAL
TABLE FOR CONVERTING BCD TO TEXT
HEX_TAB DB
"0123456789ABCDEF"
; BUFFER FOR
CONVERTING DECIMAL AND HEX NUMBERS TO STRINGS
WRITE_BUF DB
16 DUP (0), 13, 10, "$"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; GLOBAL
DESCRIPTOR TABLE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDTR DF GDT_SIZE-1
GDT_BEGIN =
$
GDT LABEL WORD
GDT_0 S_DESC <0,0,0,0,0,0> ; 00
GDT_CS16 S_DESC
<CODE16_SIZE-1,,,ACS_CODE,0,>
; 08
GDT_DS16 S_DESC
<DATA16_SIZE-1,,,ACS_DATA,0,>
; 10
GDT_SS16 S_DESC <STACK_SIZE
-1,,,ACS_STACK,0,> ; 18
GDT_BIOS S_DESC
<SIZE_BIOS-1,LOW_BIOS,HIGH_BIOS,ACS_DATA+ACS_DPL_3,0,0> ; 20
GDT_TEXT S_DESC
<SIZE_TEXT-1,LOW_TEXT,HIGH_TEXT,ACS_DATA+ACS_DPL_3,0,0> ; 28
GDT_GRAPH S_DESC
<SIZE_GRAPH-1,LOW_GRAPH,HIGH_GRAPH,ACS_DATA+ACS_DPL_3,0,0>;30
GDT_FLAT S_DESC
<0FFFFH,0,0,ACS_DATA,08FH,0> ; 4
GB SEGMENT ;)) ; 38
GDT_SIZE =
$ - GDT_BEGIN
GDT_SRC32 S_DESC <0FFFFH,,,ACS_DATA,0,> ; 40 (TEMPORARY)
GDT_DST32 S_DESC <0FFFFH,,,ACS_DATA,0,> ; 48 (TEMPORARY)
CS16_SEL =
GDT_CS16 - GDT_0
DS16_SEL =
GDT_DS16 - GDT_0
SS16_SEL =
GDT_SS16 - GDT_0
BIOS_SEL =
(GDT_BIOS - GDT_0) OR RPL_3
TEXT_SEL =
(GDT_TEXT - GDT_0) OR RPL_3
GRAPH_SEL =
(GDT_GRAPH - GDT_0) OR RPL_3
FLAT_SEL =
GDT_FLAT - GDT_0
SRC32_SEL =
GDT_SRC32 - GDT_0
DST32_SEL =
GDT_DST32 - GDT_0
;;;;;;;;;;;;;;;;
;; DUMMY IDTR ;;
;;;;;;;;;;;;;;;;
IDTR0 DF 0 ; USED FOR SWITCHING TO REAL
MODE
IDTR1 DF 3FFh
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; OTHER SYSTEM
VARIABLES ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ORIGINAL MASKS
FOR IRQS
INT_MASK_M DB
?
INT_MASK_S DB
?
; AMMOUNT OF THE
EXTENDED MEMORY ABOVE 1MB+64KB
EXT_MEMORY DD
?
; STACK POINTER
STORAGE
ESP32 DD ?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PAGE DIRECTORY
THAT IS COPIED TO THE 120000H ADDRESS ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PAGEDIR DD
110003H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PAGE TABLE THAT
IS COPIED TO THE 110000H ADDRESS ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PAGETAB LABEL
DWORD
N = 0
REPT
160
DD
N OR 3
N = N + 4096
ENDM
; N = 160*4096
; REPT
16
; DD
N OR 3
; N = N + 4096
; ENDM
N = (160+15)*4096 ; REVERSED ORDER OF PAGES IN THE VGA
BUFFER
REPT
16
DD
N OR 3
N = N - 4096
ENDM
N = (160+16)*4096
REPT
1024-(160+16)
DD
N OR 3
N = N + 4096
ENDM
DATA16_SIZE =
$ - DATA16_BEGIN
DATA16 ENDS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COMMON
REAL/PROTECTED MODE STACK SEGMENT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STACK16 SEGMENT
PARA STACK 'STACK'
DB STACK_SIZE DUP(?)
STACK16 ENDS
END MAIN
macroses.inc
(Ñòðóêòóðû çàùèùåííîãî ðåæèìà)
;--------------------------------------------------------------------;
; Macroses that
define useful structures, constants and other things ;
;--------------------------------------------------------------------;
; Pushes several
registers to the stack
@PUSH MACRO
REGLIST
IRP
REG, <REGLIST>
PUSH REG
ENDM
ENDM
; Popes several
registers from the stack
@POP MACRO
REGLIST
IRP
REG, <REGLIST>
POP REG
ENDM
ENDM
; Sets up GDT
table entry
@SET_GDT_ENTRY MACRO
MOV [BX][S_DESC.BASE_L], AX
MOV [BX][S_DESC.BASE_M], DL
MOV [BX][S_DESC.BASE_H], DH
ENDM
; Segment
Descriptor structure
S_DESC STRUC
LIMIT DW 0
BASE_L DW 0
BASE_M DB 0
ACCESS DB 0
ATTRIBS DB
0
BASE_H DB 0
S_DESC ENDS
; Interrupt
Descriptor structure
I_DESC STRUC
OFFS_L DW 0
SEL DW 0
PARAM_CNT DB
0
ACCESS DB 0
OFFS_H DW
0
I_DESC ENDS
; IDTR register
structure
R_IDTR STRUC
LIMIT DW 0
IDT_L DW 0
IDT_H DW 0
R_IDTR ENDS
; Task State
Segment structure
S_TSS STRUC
LINK DW 0,
0 ;
0
ESP0 DD 0
; 4
SS0 DW 0, 0
; 8
ESP1 DD 0
; 0C
SS1 DW 0, 0
; 10
ESP2 DD 0
; 14
SS2
DW 0, 0
; 18
R_CR3 DD 0
; 1C
R_EIP DD 0
; 20
R_EFLAGS DD
0 ; 24
R_EAX DD 0
; 28
R_ECX DD 0
; 2C
R_EDX DD 0
; 30
R_EBX DD 0
; 34
R_ESP DD 0
; 38
R_EBP DD 0
; 3C
R_ESI DD 0
; 40
R_EDI DD 0
; 44
R_ES DW 0, 0
; 48
R_CS DW 0, 0
; 4C
R_SS DW 0, 0
; 50
R_DS DW 0, 0
; 54
R_FS DW 0, 0
; 58
R_GS DW
0, 0 ; 5C
R_LDTR DW 0, 0
; 60
TRACE DW 0
; 64
IO_MAP_ADDR DW
68H ; 66
IO_MAP DB (400H SHR 3) DUP (0) ; 400H PORTS
AVAILABLE
S_TSS ENDS
; DIFFERENT
CONSTANTS AND FLAGS FOR PM
SIZE_TSS EQU
68H + (400H SHR 3)
; Access byte's
flags
ACS_PRESENT EQU 10000000B
ACS_CSEG EQU 00011000B
ACS_DSEG EQU 00010000B
ACS_EXPDOWN EQU 00000100B
ACS_CONFORM EQU 00000100B
ACS_READ EQU 00000010B
ACS_WRITE EQU 00000010B
ACS_CODE = ACS_PRESENT OR ACS_CSEG; OR
ACS_CONFORM
ACS_DATA = ACS_PRESENT OR ACS_DSEG OR
ACS_WRITE
ACS_STACK = ACS_PRESENT OR ACS_DSEG OR
ACS_WRITE
ACS_INT_GATE EQU 00001110B
ACS_TRAP_GATE EQU 00001111B
ACS_IDT EQU ACS_DATA
ACS_INT EQU ACS_PRESENT OR ACS_INT_GATE
ACS_TRAP EQU ACS_PRESENT OR ACS_TRAP_GATE
ACS_TSS EQU ACS_PRESENT OR 00001001B
ACS_DPL_0 EQU 00000000B
ACS_DPL_1 EQU 00100000B
ACS_DPL_2 EQU 01000000B
ACS_DPL_3 EQU 01100000B
RPL_0 EQU 0
RPL_1 EQU 1
RPL_2 EQU 2
RPL_3 EQU 3
; CONSTANTS FOR
BIOS DATA AREA
SEG_BIOS EQU 00040H
SIZE_BIOS EQU 00300H
LOW_BIOS EQU 00400H
HIGH_BIOS EQU 0
; CONSTANTS FOR
TEXT VIDEO MODES
SEG_TEXT EQU 0B800H
SIZE_TEXT EQU 02000H ; > 80*50*2
LOW_TEXT EQU 08000H
HIGH_TEXT EQU 0BH
; CONSTANTS FOR
GRAPHICS VIDEO MODES
SEG_GRAPH EQU 0A000H
SIZE_GRAPH EQU 10000H
LOW_GRAPH EQU 0
HIGH_GRAPH EQU 0AH
; DIFFERENT
CONSTANTS FOR PORT I/O
PORT_CMOS EQU 070H
PORT_6845 EQU 00063H
PORT_TEXT EQU 003D4H
PORT_STATUS EQU 064H
SHUT_DOWN EQU 0FEH
MODE_VIRTUAL EQU
00001H
PORT_A20 EQU 0D1H
A20_ON EQU 0DFH
A20_OFF EQU 0DDH
PORT_KBD_A EQU 060H
PORT_KBD_B EQU 061H
PORT_INT_MASK_M
EQU 021H
PORT_INT_MASK_S
EQU 0A1H
EOI EQU 020H
PORT_8259M EQU 020H
PORT_8259S EQU 0A0H
PORT_COM_REG EQU 043H
PORT_CHANNEL2 EQU 042H
; Enables A20 line
@ENABLE_A20 MACRO
MOV AL, PORT_A20
OUT PORT_STATUS, AL
MOV AL, A20_ON
OUT PORT_KBD_A, AL
ENDM
; Disables A20
line
@DISABLE_A20 MACRO
MOV AL, PORT_A20
OUT PORT_STATUS, AL
MOV AL, A20_OFF
OUT PORT_KBD_A, AL
ENDM
; Enables
non-maskable interrupts
@ENABLE_NMI MACRO
MOV AL, 0DH
OUT PORT_CMOS, AL
JMP $+2
ENDM
; Disables
non-maskable interrupts
@DISABLE_NMI MACRO
MOV AL, 8FH
OUT PORT_CMOS, AL
JMP $+2
ENDM
; This macro
reprograms PIC (master and slave) to other interrupt vectors
@SET_INT_CTRLR MACRO
INT_MASTER, INT_SLAVE
MOV
AL, 11H ; START
8259 INITIALIZATION
OUT
PORT_8259M, AL
OUT
PORT_8259S, AL
MOV
AL, INT_MASTER ; BASE
INTERRUPT VECTOR
OUT
PORT_8259M+1, AL
MOV
AL, INT_SLAVE
OUT
PORT_8259S+1, AL
MOV
AL, 1 SHL 2 ; BITMASK
FOR CASCADE ON IRQ 2
OUT
PORT_8259M+1, AL
MOV
AL, 2 ; CASCADE
ON IRQ 2
OUT
PORT_8259S+1, AL
MOV AL, 1 ; FINISH 8259 INITIALIZATION
OUT
PORT_8259M+1, AL
OUT
PORT_8259S+1, AL
MOV
AL, 0FFH ; MASK ALL
INTERRUPTS
OUT
PORT_INT_MASK_M, AL
OUT
PORT_INT_MASK_S, AL
ENDM
@JUMP MACRO ; OVERLOADS CODE SELECTOR AFTER
CHANGING ITS DESCRIPTOR
DB
0EAH
DW
$+4
DW
CS16_SEL
ENDM
@JUMPR MACRO ; OVERLOADS CODE SEGMENT
DB
0EAH
DW
$+4
DW
CODE16
ENDM
@RETF MACRO ; FAR RETURN FROM 16-BIT TO 32-BIT
CODE & VICE VERSA
DB
66H
RETF
ENDM
detect.inc (Îïðåäåëåíèå
êîíôèãóðàöèè ñèñòåìû)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Detects Real
Mode and hardware ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.8086
DETECT PROC NEAR
;;;;;;;;;;;;;;;;;;;;;;;;
;; DETECTING CPU
TYPE ;;
;;;;;;;;;;;;;;;;;;;;;;;;
CALL
CPU_CHECK
CMP
AL, 3
JNC
DETECT_IS_386_PLUS ; 386+
LEA
DX, MSG_NEEDED_386
MOV
AH, 9
INT
21H
JMP
DETECT_FAILED
DETECT_IS_386_PLUS:
.386P
;;;;;;;;;;;;;;;;;;;;;;;;;
;; DETECTING REAL
MODE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;
SMSW
AX ; BUT THIS WORKS PERFECTLY :)
TEST
AL, 1 ;
IS PROTECTED MODE ACTIVE?
JZ
DETECT_IS_REAL_MODE ;
NO, IT ISN'T (REAL MODE)
LEA
DX, MSG_NEEDED_RM
MOV
AH, 9
INT
21H
JMP
DETECT_FAILED ;
YES, IT IS. EXITING...
DETECT_IS_REAL_MODE:
;;;;;;;;;;;;;;;;;;;;;;;;;
;; DETECTING
HIMEM.SYS ;;
;;;;;;;;;;;;;;;;;;;;;;;;;
MOV
AX, 4300H
INT
2FH
CMP
AL, 80H
JNE
DETECT_NO_HIMEM ;
HIMEM.SYS IS NOT INSTALLED
LEA
DX, MSG_FOUND_HIMEM
MOV
AH, 9
INT
21H
JMP
DETECT_FAILED ;
YES, IT IS. EXITING...
DETECT_NO_HIMEM:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; DETECTING VIDEO
SYSTEM ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV
AX,1A00H
INT
10H ; check if VGA
type display
CMP
AL,1AH
JNE
DETECT_Not_VGA
CMP
BL,7 ; VGA with Monochrome Display?
JE
DETECT_IS_VGA
CMP
BL,8 ; VGA with Color
Display?
JE
DETECT_IS_VGA
DETECT_NOT_VGA:
LEA
DX, MSG_NEEDED_VGA
MOV
AH, 9
INT
21H
JMP DETECT_FAILED
DETECT_IS_VGA:
MOV
AX, 1003H
MOV
BL, 0
INT
10H ; DISABLE BLINKING
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COUNTING
EXTENDED MEMORY ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CALL
MEM_COUNT
MOV
DS:[EXT_MEMORY], EAX ; bytes
above 1MB+64KB
RET
DETECT_FAILED:
MOV AX, 4C00H
INT 21H
DETECT ENDP
.8086
CPU_CHECK PROC
NEAR
; 8086 CPU check
; Bits 12-15 are always set on the 8086
processor
;
CC_check_8086:
pushf ;save FLAGS
pop
bx ;store
FLAGS in BX
mov
ax, 0fffh ;clear
bits 12-15
and
ax, bx ; in FLAGS
push
ax ;store new
FLAGS calue on stack
popf ;replace current
FLAGS value
pushf ;set new flags
pop
ax ;store new
flags in AX
and ax, 0f000h ;if bits 12-15 are set, then CPU
cmp
ax, 0f000h ; is an 8086/8088
mov
al, 0 ; save the
CPU type to AL
je
CC_end_cpuid
;
; Intel 286 CPU check
; Bits 12-15 are always clear on the Intel
processor.
;
check_80286:
.286
or
bx, 0f000h ;try to
set bits 12-15
push
bx
popf
pushf
pop
ax
and
ax, 0f000h ; if bits
12-15 are cleared,
; CPU=Intel 286
mov
al, 2 ; turn on
Intel 286 Cpu flag
jz
CC_end_cpuid ; if CPU
is intel 286, check
; for Intel 287 math coprocessor
MOV
AL, 3 ; 386+
.8086
CC_END_CPUID:
RET
CPU_CHECK ENDP
.386P
MEM_COUNT PROC
NEAR
@ENABLE_A20
Xor
EAX, EAX
Mov
AX, CS
Shl
EAX, 4
LEA
EDX, MC_GDT
Add
EAX, EDX
Mov
DWord Ptr CS:MC_GDTR+2, EAX; Fill in GDTR with physical address
; of
Global Descriptor Table
@Push
<DS, ES>
CLI
LGDT
FWord Ptr CS:MC_GDTR ; Load
Global Descriptor Table
Mov
EAX, 1
Mov
CR0, EAX ; Set
Protected Mode
Mov
AX, 8
Mov
DS, AX
Mov
ES, AX
Mov
FS, AX
Mov
GS, AX ; All segment registers are loaded
; with
4GB segment's selector
Xor
EAX, EAX
Mov
CR0, EAX ; Set Real
Mode
STI
Xor
ECX, ECX ; 0 bytes
Mov
DS, CX
Mov
ES, CX
Mov
ESI, 110000H ; 1MB +
64KB
Mov
EDI, ESI
MC_cycle:
Mov
EAX, DS:[ESI]
Not
EAX
Mov
ES:[EDI], EAX
Mov
EBX, DS:[ESI]
Cmp
EAX, EBX
JNE
MC_failed
Add
ESI, 4096;4
Mov
EDI, ESI
Add
ECX, 4096;4
Jmp
MC_cycle
MC_failed:
; And
CX, 0FC00H ; round to
1KB
Mov
EBX, ECX
; SHR
ECX, 2
; MOV
EDI, 110000H
; XOR
EAX, EAX
; MOV
ES, AX
; CLD
;MC_MEMCYC:
; MOV
ES:[EDI], EAX ; CLEAR
MEMORY
; ADD
EDI, 4
; DEC
ECX
; JNZ
MC_MEMCYC
@DISABLE_A20
MOV
EAX, EBX
@Pop
<ES, DS>
RET
MC_GDT DQ
0, 8F92000000FFFFh ;
"0" & "4GB" Descriptors
MC_GDTR DW
16, 0, 0
MEM_COUNT ENDP
cpyblck.inc (Êîïèðîâàíèå áëîêà
ïàìÿòè)
; FUNCTION FOR
COPYING MEMORY BLOCKS
; ESI = SOURCE
32-BIT OFFSET
; EDI = TARGET
32-BIT OFFSET
; ECX = 16-BIT
COUNT (64 KB = MAX)
; NOTE #1: INT 15H
/ FUNCTION 87H IS NOT USED ANY MORE! (FOR COMPATITBILITY)
; NOTE #2: A20 IS
ENABLED AT THE BEGINNING OF THE ROUTINE AND DISABLED AT THE END
COPY_BLOCK PROC
NEAR
PUSHFD
@PUSH <DS, ES, FS, GS>
PUSHAD
MOV AX, DATA16
MOV DS, AX
MOV ES, AX
MOV AX, WORD PTR [GDTR]
PUSH
AX
ADD WORD PTR [GDTR], 16
@PUSH <ESI, EDI, ECX>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BEGINNING OF
THE GDT SETUP ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV
EAX, DS
SHL
EAX, 4
ADD
EAX, OFFSET GDT
MOV
DWORD PTR [GDTR+2], EAX
MOV
AX, DS
MOV
DL, AH
XOR
DH, DH
SHL
AX, 4
SHR
DX, 4
MOV
SI, AX
MOV
DI, DX
; 16-BIT
REAL/PROTECTED MODE MAIN TASK CODE GOES HERE
LEA
BX, GDT_CS16
MOV
AX, CS
XOR
DH, DH
MOV
DL, AH
SHL
AX, 4
SHR
DX, 4
@SET_GDT_ENTRY
; COMMON DATA
SEGMENT GOES HERE
LEA
BX, GDT_DS16
MOV
AX, SI
MOV
DX, DI
@SET_GDT_ENTRY
; STACK FOR 16/32
REAL/PROTECTED MODE MAIN TASK GOES HERE
LEA
BX, GDT_SS16
MOV
AX, SS
XOR
DH, DH
MOV
DL, AH
SHL
AX, 4
SHR
DX, 4
@SET_GDT_ENTRY
@POP <ECX, EDI, ESI>
;;;;;;;;;;;;;;;;;;;;;;;;;
;; DATA BLOCKS GO
HERE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;
MOV GDT_SRC32.BASE_L, SI
MOV EAX, ESI
SHR EAX, 16
MOV GDT_SRC32.BASE_M, AL
MOV GDT_SRC32.BASE_H, AH
MOV GDT_DST32.BASE_L, DI
MOV EAX, EDI
SHR EAX, 16
MOV GDT_DST32.BASE_M, AL
MOV GDT_DST32.BASE_H, AH
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PMODE
INITIALIZATION STARTS HERE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ENABLE_A20 ; ENABLE A20 LINE
IN
AL, PORT_INT_MASK_M
MOV
[INT_MASK_M], AL ;
SAVE MASK OF HARDWARE INTS AT MASTER CNTRLR
IN
AL, PORT_INT_MASK_S
MOV
[INT_MASK_S], AL ;
SAVE MASK OF HARDWARE INTS AT SLAVE CNTRLR
CLI ; DISABLE MASKABLE INTS
@DISABLE_NMI ; DISABLE
NON-MASKABLE INTS
LGDT
[GDTR] ;
LOAD GDTR
MOV
EAX, CR0
AND
EAX, 01111111111111111111111111110000B
OR
EAX, 00000000000000000000000000000001B
MOV
CR0, EAX ;
SET UP PROTECTED MODE
@JUMP ; OVERLOAD
CODE SELECTOR
MOV
AX, DS16_SEL
MOV
DS, AX
MOV
ES, AX
MOV
AX, SS16_SEL
MOV
SS, AX ;
LOAD SS WITH STACK SELECTOR
XOR
AX, AX
MOV
FS, AX
MOV
GS, AX
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ACTUAL TRANSFERR
GOES HERE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV
AX, SRC32_SEL
MOV
DS, AX
MOV
AX, DST32_SEL
MOV
ES, AX
XOR
SI, SI
XOR
DI, DI
CLD
SHR
ECX, 1
JNC
CB_CONT
MOVSB
CB_CONT:
REP
MOVSW
;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BACK TO REAL
MODE... ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV
AX, DS16_SEL
MOV
DS, AX
MOV
ES, AX
MOV
[ESP32], ESP
MOV
AX, BIOS_SEL
MOV
ES, AX
MOV
WORD PTR ES:[067H], OFFSET CB_SHUTDOWN_RET
MOV
WORD PTR ES:[069H], CODE16
MOV
AL, 5
OUT
PORT_CMOS+1, AL
; MOV
AL, SHUT_DOWN
; OUT
PORT_STATUS, AL
LIDT
[IDTR0]
INT
0
;CB_RESET:
; HLT
; JMP
CB_RESET
CB_SHUTDOWN_RET:
MOV
AX, DATA16
MOV
DS, AX
MOV
ES, AX
MOV
AX, STACK16
MOV
SS, AX
MOV
ESP, [ESP32]
XOR
AX, AX
MOV
FS, AX
MOV
GS, AX
MOV
AL, [INT_MASK_M]
OUT
PORT_INT_MASK_M, AL ;
RESTORE MASK OF HARDWARE INTS AT MASTER CNTRLR
MOV
AL, [INT_MASK_S]
OUT
PORT_INT_MASK_S, AL ;
RESTORE MASK OF HARDWARE INTS AT SLAVE CNTRLR
@ENABLE_NMI ; ENABLE
NON-MASKABLE INTS
STI ; ENABLE
MASKABLE INTS
@DISABLE_A20 ; DISABLE A20 LINE
POP AX
MOV WORD PTR [GDTR], AX
POPAD
@POP <GS, FS, ES, DS>
POPFD
RET
COPY_BLOCK ENDP
num2str.inc (Ïåðåâîä ÷èñëà â
ñòðîêó)
;------------------------------------------------;
; SET OF FUNCTIONS
CONVERTING NUMBERS TO STRINGS ;
;------------------------------------------------;
; FUNCTION:
CONVERTS THE EAX VALUE TO THE 8-BYTE HEXADECIMAL STRING
; IN: EAX = 32-BIT VALUE, ES:DI = OUTPUT BUFFER
; OUT: NONE, ALL
REGS ARE SAVED
HEX2STR PROC NEAR
PUSH
DS
PUSHAD
MOV
DX, DATA16
MOV
DS, DX
LEA
SI, HEX_TAB
MOV
CX, 8
H2S_1:
ROL
EAX, 4
MOVZX
BX, AL
AND
BL, 0FH
MOV
BL, DS:[SI+BX]
MOV
ES:[DI], BL
INC
DI
LOOP
H2S_1
POPAD
POP
DS
RET
HEX2STR ENDP
; FUNCTION:
CONVERTS THE EAX VALUE TO THE 10-BYTE DECIMAL STRING
; IN: EAX = 32-BIT VALUE, ES:DI = OUTPUT BUFFER
; OUT: NONE, ALL
REGS ARE SAVED
DEC2STR PROC NEAR
PUSHAD
MOV
EBX, 10
XOR
CX, CX
D2S_CYCLE:
XOR
EDX, EDX
DIV
EBX
PUSH
DX
INC
CX
OR
EAX, EAX
JNZ
D2S_CYCLE
MOV
DX, 10
SUB
DX, CX
D2S_CYC1:
POP
AX
ADD
AL, '0'
MOV
ES:[DI], AL
INC
DI
LOOP
D2S_CYC1
MOV
CX, DX
JCXZ
D2S_DONE
MOV
AL, 0
D2S_CYC2:
MOV
ES:[DI], AL
INC
DI
LOOP
D2S_CYC2
D2S_DONE:
POPAD
RET
DEC2STR ENDP
set_rm1.inc (Âîçâðàò â RealMode – ñïîñîá 1)
;--------------------------------------------------------------------------;
; Sets Real Mode
using CR0, overloading segs and reprogramming PIC ;
; Ver 1:
Unfortunately, works quite buggy. I don't know why. :(( ;
; Ver 2: It seems
to be everything is OK after changing order of the ;
; @SET_INT_CTRLR 08H, 70H and ;
; LIDT FWORD PTR IDTR ;
; instructions ;
; Ver 3: unchanged
vesrsion 2, but it doesn't work again when the task ;
; switching is enabled ;
; Ver 4: added a
"CLTS" instructio. Every DPMI-based program, that I tried ;
; to run immediately after quitting from
this program, just hanged ;
; with nonzero "task switched"
flag. The solution is inside this ;
; simple instruction. Viola! it
works! ;
;--------------------------------------------------------------------------;
CLTS ; THE
SOLUTION!!! ;-)
@SET_INT_CTRLR 08H, 70H ; REINITIALISE MASTER &
SLAVE INT CONTROLLERS
MOV
GDT_CS16.LIMIT, 0FFFFH ;
CODE SEGMENT HAS 64KB LIMIT
MOV
GDT_DS16.LIMIT, 0FFFFH ;
DATA SEGMENT HAS 64KB LIMIT
MOV
GDT_SS16.LIMIT, 0FFFFH ;
STACK SEGMENT HAS 64KB LIMIT
; LGDT
FWORD PTR GDT_GDT ;
LOAD GDTR
@JUMP ; OVERLOAD
CODE SELECTOR
MOV
AX, DS16_SEL
MOV
DS, AX ;
OVERLOAD DATA SELECTOR
MOV
ES, AX ;
OVERLOAD DATA SELECTOR
MOV
FS, AX ;
OVERLOAD DATA SELECTOR
MOV
GS, AX ;
OVERLOAD DATA SELECTOR
MOV
AX, SS16_SEL
MOV
SS, AX ;
OVERLOAD STACK SELECTOR
MOV
EAX, CR0
AND
EAX, 01111111111111111111111111111110B
MOV
CR0, EAX ;
BACK TO THE REAL MODE
@JUMPR ; RESTORE RM
CODE SEGMENT
MOV
AX, STACK16
MOV
SS, AX ;
RESTORE RM STACK SEGMENT
MOV
AX, DATA16
MOV
DS, AX ;
RESTORE RM DATA SEGMENT
MOV
ES, AX
XOR
AX, AX
MOV
FS, AX
MOV
GS, AX
LIDT
FWORD PTR IDTR1 ;
LOAD REAL MODE INT TABLE
set_rm2.inc (Âîçâðàò â RealMode – ñïîñîá 2)
;--------------------------------;
; Sets Real Mode
using CPU reset ;
; Works perfectly.
:)) ;
;--------------------------------;
MOV
ESP32, ESP
MOV
AX, BIOS_SEL
MOV
ES, AX
MOV
WORD PTR ES:[067H], OFFSET SHUTDOWN_RET
MOV
WORD PTR ES:[069H], CODE16
MOV
AL, 5
OUT
PORT_CMOS+1, AL
; MOV
AL, SHUT_DOWN
; OUT
PORT_STATUS, AL
;START_RESET:
; HLT
; JMP
START_RESET
LIDT
[IDTR0]
INT
0
SHUTDOWN_RET LABEL FAR
MOV
AX, DATA16
MOV
DS, AX
MOV
ES, AX
MOV
AX, STACK16
MOV
SS, AX
MOV
ESP, ESP32
XOR
AX, AX
MOV
FS, AX
MOV
GS, AX
setupgdt.inc
(Èíèöèàëèçàöèÿ GDT)
;-----------------;
; SETS UP THE GDT
;
;-----------------;
SETUP_GDT PROC
MOV
EAX, DS
SHL
EAX, 4
ADD
EAX, OFFSET GDT
MOV
DWORD PTR [GDTR+2], EAX
MOV
AX, DS
MOV
DL, AH
XOR
DH, DH
SHL
AX, 4
SHR
DX, 4
MOV
SI, AX
MOV
DI, DX
; 16-BIT
REAL/PROTECTED MODE MAIN TASK CODE GOES HERE
LEA
BX, GDT_CS16
MOV
AX, CS
XOR
DH, DH
MOV
DL, AH
SHL
AX, 4
SHR
DX, 4
@SET_GDT_ENTRY
; COMMON DATA
SEGMENT GOES HERE
LEA
BX, GDT_DS16
MOV
AX, SI
MOV
DX, DI
@SET_GDT_ENTRY
; STACK FOR 16/32
REAL/PROTECTED MODE MAIN TASK GOES HERE
LEA
BX, GDT_SS16
MOV
AX, SS
XOR
DH, DH
MOV
DL, AH
SHL
AX, 4
SHR
DX, 4
@SET_GDT_ENTRY
RET
SETUP_GDT ENDP