4

 

, , , . , , . . , , .

( , *.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