Ïðèìåð ¹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