Ïðèìåð ¹3 – «ßäðî êðîøå÷íîé îïåðàöèîííîé ñèñòåìû – Kernel».

 

           ýòîì ïðèìåðå «ïàðàëëåëüíî» âûïîëíÿþòñÿ äâå çàäà÷è, èõ âûïîëíåíèå ìîæíî íàáëþäàòü íà ýêðàíå. Òàê æå îáðàáàòûâàåòñÿ ïðåðûâàíèå îò êëàâèàòóðû: ñêàí-êîä íàæàòîé êëàâèøè âûâîäèòñÿ íà ýêðàíå.

          Íèæå ïðèâåäåí èñõîäíûé òåêñò ïðîãðàììû (ñíà÷àëà ãëàâíûé ìîäóëü, à çà íèì «âêëþ÷àåìûå» *.inc - ìîäóëè).

 

kernel.asm

 

        .386P

        .MODEL   LARGE

 

        INCLUDE MACROSES.INC                    ; MAIN DEFINITIONS

 

SIZE_STACK      EQU     1000H

 

;-----------------------------------------;

; 16-BIT REAL/PROTECTED NODE CODE SEGMENT ;

;-----------------------------------------;

 

CODE16  SEGMENT PARA USE16

CODE16_BEGIN    =       $

        ASSUME          CS:CODE16,DS:DATA,ES:DATA

START:

        MOV     AX, DATA

        MOV     DS, AX

        MOV     ES, AX                          ; LOAD DATA SEGMENTS

 

        LEA     DX, MSG_STARTUP

        MOV     AH, 9

        INT     21H

 

;        MOV     EAX, CR0                       ; DOESN'T WORK UNDER WIN :(

        SMSW    AX                              ; BUT THIS WORKS PERFECTLY :)

        TEST    AL, 1                           ; IS PROTECTED MODE ACTIVE?

        JZ      START_NO_PM                     ; NO, IT ISN'T

        LEA     DX, MSG_VM

        MOV     AH, 9

        INT     21H

        JMP     START_EXIT                      ; YES, IT IS. EXITING...

 

START_NO_PM:

        MOV     EAX, 3

        CALL    delayRTC

 

        @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

 

        INCLUDE SETUPGDT.INC                    ; FILL GDT

        INCLUDE SETUPIDT.INC                    ; FILL IDT

        LGDT    FWORD PTR GDT_GDT               ; LOAD GDTR

        LIDT    FWORD PTR IDTR                  ; LOAD IDTR

 

        MOV     EAX, CR0

        OR      AL, 1

        MOV     CR0, EAX                        ; SET UP PROTECTED MODE

 

        @JUMP                                   ; OVERLOAD CODE SELECTOR

        MOV     AX, DS_DESC

        MOV     DS, AX                          ; LOAD DS WITH DATA SELECTOR

        MOV     ES, AX                          ; LOAD ES WITH DATA SELECTOR

        MOV     AX, SS_DESC

        MOV     SS, AX                          ; LOAD SS WITH STACK SELECTOR

 

        XOR     AX, AX

        MOV     FS, AX                          ; LOAD FS WITH 0

        MOV     GS, AX                          ; LOAD GS WITH 0

        LLDT    AX                              ; LOAD LDTR WITH 0

 

        MOVZX   ESP, SP                         ; EXPAND SP TO ESP

        PUSH    CS                              ; PREPARE FOR RETURNING BACK

        PUSH    OFFSET START_BACK_TO_16         ; TO 16-BIT PM CODE

        MOV     DS:[ESP32], ESP

 

        LEA     EDI, ENTER_32

        MOV     EAX, CS32_DESC

        PUSH    EAX

        PUSH    EDI                             ; PUSH 32-BIT CODE ADDRESS

 

        INCLUDE SETUPTSS.INC                    ; FILL TSSs

        MOV     AX, TSS_MAIN_DESC

        LTR     AX                              ; LOAD TR REGISTER

 

        @SET_INT_CTRLR 20H, 28H                 ; REINITIALISE MASTER & SLAVE INT CONTROLLERS

        MOV     AL, 0                           ; MASK = 0

        OUT     PORT_INT_MASK_M, AL             ; UNMASK INTS

        OUT     PORT_INT_MASK_S, AL             ; UNMASK INTS

        @ENABLE_NMI                             ; ENABLE NON-MASKABLE INTS

        STI                                     ; ENABLE MASKABLE INTS

 

        @RETF                                   ; "RETURN" TO 32-BIT CODE

 

START_BACK_TO_16:

        CLI                                     ; DISABLE MASKABLE INTS

        @DISABLE_NMI                            ; DISABLE NON-MASKABLE INTS

        MOV     AX, DS_DESC

        MOV     DS, AX                          ; SAFETY IS WHAT WE NEED!!!

 

        INCLUDE SET_RM1.INC                     ; BACK TO REAL MODE

 

        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

 

START_EXIT:

        MOV     EAX, 3

        CALL    delayRTC

 

        MOV     AX, 3

        INT     10H

 

        LEA     DX, MSG_CONTACT

        MOV     AH, 9

        INT     21H

        MOV     AX, 4C00H

        INT     21H                             ; EXIT TO DOS

 

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

SIZE_CSEG16     =       ($ - CODE16_BEGIN)

CODE16  ENDS

 

;------------------------------------;

; 32-BIT PROTECTED MODE CODE SEGMENT ;

;------------------------------------;

 

CODE32  SEGMENT PARA USE32

CODE32_BEGIN    =       $

        ASSUME          CS:CODE32,DS:DATA,ES:DATA

 

;--------------------;

; MAIN TASK (RING 0) ;

;--------------------;

 

ENTER_32:

        CALL    CLRSCR

        XOR     EDI, EDI

 

        LEA     ESI, MSG_TASK_MAIN

        CALL    W_ASCIIZ

        ADD     EDI, 80*2

        LEA     ESI, MSG_SCAN_CODE

        CALL    W_ASCIIZ

        ADD     EDI, 15*2

 

ENTER_32_WAIT_KEY:

        MOV     BL, KEY_SCAN_CODE

        MOVZX   EAX, BL

        CALL    W_EAX

 

        ADD     EDI, (80-15)*2

        MOV     EAX, ESP

        CALL    W_EAX                           ; VISUAL TEST OF ESP

        SUB     EDI, (80-15)*2

 

        CMP     BL, 1                           ; ESC?

        JNE     ENTER_32_WAIT_KEY               ; NOT ESC

 

;        MOV     ECX, 0FFFFFFFH

;        LOOP    $                               ; DOES A FEW SECOND DELAY ON MY P233

 

        @RETF                                   ; BACK TO 16-BIT CODE

 

;----------------------------------------------;

; MAIN ROUTINES AND HANDLERS ARE INCLUDED HERE ;

;----------------------------------------------;

 

        INCLUDE SCREENIO.INC                    ; SCREEN I/O ROUTINES

        INCLUDE EXC.INC                         ; EXCEPTION HANDLER

        INCLUDE IRET.INC                        ; TIMER INTERRUPT HANDLER

        INCLUDE TIMER.INC                       ; KEYBOARD INTERRUPT HANDLER

        INCLUDE KEYBOARD.INC                    ; ROUTINE FOR DISPLAYING TSS

        INCLUDE SHOW_TSS.INC                    ; SERVICE INTERRUPT

        INCLUDE SERVICE.INC

SIZE_CSEG32     =       ($ - CODE32_BEGIN)

CODE32  ENDS

 

;-----------------------------------------;

; COMMON REAL/PROTECTED MODE DATA SEGMENT ;

;-----------------------------------------;

 

DATA    SEGMENT PARA USE16

DATA_BEGIN      =       $

        INCLUDE GDT.INC                         ; GDT TABLE

        INCLUDE IDT.INC                         ; IDT TABLE

        INCLUDE TSS.INC                         ; TSS TABLES

 

MSG_STARTUP     DB      "Tiny OS Kernel 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_VM  DB              "PROCESSOR IS ALREADY IN PROTECTED MODE.",13,10

        DB              "PROBABLY WINDOWS OR EMM386.EXE IS LOADED.",13,10

        DB              "LOAD PURE DOS OR WINDOWS IN COMMAND PROMPT ONLY MODE.",13,10

        DB              "EXITING...",13,10,"$"

HEX_TAB DB              "0123456789ABCDEF"

 

EXC_ERR DB              0,0,0,0,0,0,0,0, 1,0,1,1,1,1,1,0, 0,1

MSG_EXC DB              "EXCEPTION: ",0

MSG_EXC_ERR DB          "ERROR CODE: ",0

MSG_CSEIP DB            "CS=XXXXXXXX EIP=XXXXXXXX",0

 

INT_MASK_M DB           ?

INT_MASK_S DB           ?

ESP32   DD              ?

 

TIMER_CNT DW            0

KEY_SCAN_CODE DB        0

 

MSG_TASK_MAIN DB        "MAIN TASK",0

MSG_SCAN_CODE DB        "KBD SCAN CODE: ",0

MSG_TASK_0 DB           "TASK #0",0

MSG_TASK_1 DB           "TASK #1",0

 

MSG_TSS LABEL BYTE

        DB "CR3  = XXXXXXXX FLAGS= XXXXXXXX",0

        DB "EIP  = XXXXXXXX CS   = XXXXXXXX",0

        DB "ESP  = XXXXXXXX SS   = XXXXXXXX",0

        DB "DS   = XXXXXXXX ES   = XXXXXXXX",0

        DB "FS   = XXXXXXXX GS   = XXXXXXXX",0

        DB "EAX  = XXXXXXXX EBX  = XXXXXXXX",0

        DB "ECX  = XXXXXXXX EDX  = XXXXXXXX",0

        DB "ESI  = XXXXXXXX EDI  = XXXXXXXX",0

        DB "EBP  = XXXXXXXX LINK = XXXXXXXX",0

        DB "ESP0 = XXXXXXXX SS0  = XXXXXXXX",0

        DB "ESP1 = XXXXXXXX SS1  = XXXXXXXX",0

        DB "ESP2 = XXXXXXXX SS2  = XXXXXXXX",0

        DB "LDTR = XXXXXXXX IO/T = XXXXXXXX",0

 

OFFS_TSS LABEL DWORD

        DD 1CH, 24H

        DD 20H, 4CH

        DD 38H, 50H

        DD 54H, 48H

        DD 58H, 5CH

        DD 28H, 34H

        DD 2CH, 30H

        DD 40H, 44H

        DD 3CH, 00H

        DD 04H, 08H

        DD 0CH, 10H

        DD 14H, 18H

        DD 60H, 64H

SIZE_DSEG       =       ($ - DATA_BEGIN)

DATA    ENDS

 

;-----------------------------------;

; REAL/PROTECTED MODE STACK SEGMENT ;

;-----------------------------------;

 

SSTACK  SEGMENT PARA STACK

        DB      SIZE_STACK DUP (?)

SSTACK  ENDS

 

;-----------------------------;

; 2 ADDITIONAL TASKS (RING 3) ;

;-----------------------------;

 

        INCLUDE TASKS.INC

 

END     START

 

gdt.inc (Îïèñàíèå GDT)

 

;-----------;

; GDT Table ;

;-----------;

 

GDT_BEGIN       =       $

GDT     LABEL           WORD

        GDT_0           S_DESC <0,0,0,0,0,0>                                            ; 00

        GDT_GDT         S_DESC <GDT_SIZE-1,,,ACS_DATA,0,>                               ; 08

        GDT_CS16        S_DESC <SIZE_CSEG16-1,,,ACS_CODE,0,>                            ; 10

        GDT_DS          S_DESC <SIZE_DSEG-1,,,ACS_DATA+ACS_DPL_3,0,>                    ; 18

        GDT_SS          S_DESC <SIZE_STACK-1,,,ACS_DATA,0,>                             ; 20

        GDT_BIOS        S_DESC <SIZE_BIOS-1,LOW_BIOS,HIGH_BIOS,ACS_DATA+ACS_DPL_3,0,0>  ; 28

        GDT_TEXT        S_DESC <SIZE_TEXT-1,LOW_TEXT,HIGH_TEXT,ACS_DATA+ACS_DPL_3,0,0>  ; 30

        GDT_GRAPH       S_DESC <SIZE_GRAPH-1,LOW_GRAPH,HIGH_GRAPH,ACS_DATA+ACS_DPL_3,0,0>;38

        GDT_FLAT        S_DESC <0FFFFH,0,0,ACS_DATA,08FH,0>    ; 4 GB SEGMENT ;))       ; 40

        GDT_CS32        S_DESC <SIZE_CSEG32-1,,,ACS_CODE+ACS_READ,0,>                   ; 48

        GDT_IDT         S_DESC <SIZE_IDT-1,,,ACS_IDT,0,>                                ; 50

 

        GDT_CS_0        S_DESC <SIZE_CS_0-1,,,ACS_CODE+ACS_DPL_3,0,>                    ; 58

        GDT_CS_1        S_DESC <SIZE_CS_1-1,,,ACS_CODE+ACS_DPL_3,0,>                    ; 60

        GDT_SS_0        S_DESC <SIZE_STACK-1,,,ACS_DATA+ACS_DPL_3,0,>                   ; 68

        GDT_SS_1        S_DESC <SIZE_STACK-1,,,ACS_DATA+ACS_DPL_3,0,>                   ; 70

 

        GDT_TSS_MAIN    S_DESC <SIZE_TSS-1,,,ACS_TSS,0,>                                ; 78

        GDT_TSS_0       S_DESC <SIZE_TSS-1,,,ACS_TSS,0,>                                ; 80

        GDT_TSS_1       S_DESC <SIZE_TSS-1,,,ACS_TSS,0,>                                ; 88

GDT_SIZE        =       ($ - GDT_BEGIN)

 

CS16_DESC       =               (GDT_CS16 - GDT_0)

DS_DESC         =               (GDT_DS - GDT_0)        + RPL_3

SS_DESC         =               (GDT_SS - GDT_0)

BIOS_DESC       =               (GDT_BIOS - GDT_0)      + RPL_3

TEXT_DESC       =               (GDT_TEXT - GDT_0)      + RPL_3

GRAPH_DESC      =               (GDT_GRAPH - GDT_0)     + RPL_3

FLAT_DESC       =               (GDT_FLAT - GDT_0)

CS32_DESC       =               (GDT_CS32 - GDT_0)

IDT_DESC        =               (GDT_IDT - GDT_0)

CS_0_DESC       =               (GDT_CS_0 - GDT_0)      + RPL_3

CS_1_DESC       =               (GDT_CS_1 - GDT_0)      + RPL_3

SS_0_DESC       =               (GDT_SS_0 - GDT_0)      + RPL_3

SS_1_DESC       =               (GDT_SS_1 - GDT_0)      + RPL_3

TSS_MAIN_DESC   =               (GDT_TSS_MAIN - GDT_0)

TSS_0_DESC      =               (GDT_TSS_0 - GDT_0)

TSS_1_DESC      =               (GDT_TSS_1 - GDT_0)

 

idt.inc (Îïèñàíèå IDT)

 

;-----------;

; IDT Table ;

;-----------;

 

IDTR    R_IDTR  <SIZE_IDT,0,0>

DUMMY_IDT       DF 0

 

IDT     LABEL           WORD

IDT_BEGIN       =       $

IRPC            N, 0123456789ABCDEF

        IDT_0&N         I_DESC <0, CS32_DESC, 0, ACS_TRAP, 0>   ; 00...0F

ENDM

IRPC            N, 0123456789ABCDEF

        IDT_1&N         I_DESC <0, CS32_DESC, 0, ACS_TRAP, 0>   ; 10...1F

ENDM

        IDT_TIMER       I_DESC <0, CS32_DESC, 0, ACS_INT, 0>    ; 20

        IDT_KEYBOARD    I_DESC <0, CS32_DESC, 0, ACS_INT, 0>    ; 21

IRPC            N, 23456789ABCDEF

        IDT_2&N         I_DESC <0, CS32_DESC, 0, ACS_INT, 0>    ; 22...2F

ENDM

        IDT_SERVICE     I_DESC <0, CS32_DESC, 0, ACS_TRAP+ACS_DPL_3, 0>   ; 30

SIZE_IDT        =       ($ - IDT_BEGIN)

 

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 OR ACS_EXPDOWN

 

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_DESC

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

 

tss.inc (Îïèñàíèå TSS)

 

;---------------------------------------;

; TSSs of main and few additional tasks ;

;---------------------------------------;

 

TSS_MAIN        S_TSS   <>

TSS_0           S_TSS   <>

TSS_1           S_TSS   <>

 

; TASK LIST

TASK_LIST       DW      TSS_MAIN_DESC, TSS_0_DESC, TSS_1_DESC, 0

 

; THIS INDEX VARIABLE IS USED TO CHOSE THE TASK TO SWITCH TO

TASK_INDEX      DW      2

 

; THIS 6-BYTE PM ADDRESS IS USED TO PERFORM FAR JUMP TO TSS

TASK_ADDR       DF      0

 

iret.inc (Ïðîãðàììèðîâàíèå êîíòðîëëåðà ïðåðûâàíèé)

 

;-------------------------------------;

; Dummy IRets for hardware interrupts ;

;-------------------------------------;

 

DUMMY_IRET0 PROC NEAR

        PUSH    EAX

        MOV     AL, EOI

        OUT     PORT_8259M, AL

        POP     EAX

        IRETD

DUMMY_IRET0 ENDP

 

DUMMY_IRET1 PROC NEAR

        PUSH    EAX

        MOV     AL, EOI

        OUT     PORT_8259M, AL

        OUT     PORT_8259S, AL

        POP     EAX

        IRETD

DUMMY_IRET1 ENDP

 

keyboard.inc (Îáðàáîò÷èê ïðåðûâàíèÿ îò êëàâèàòóðû)

 

;-------------------------------------;

; Keyboard hardware interrupt handler ;

;-------------------------------------;

 

KEYBOARD_HANDLER PROC NEAR

        @PUSH   <DS, EAX>

        MOV     AX, DS_DESC

        MOV     DS, AX

 

        IN      AL, PORT_KBD_A

        MOV     AH, AL

        AND     AL, 07FH

 

        MOV     DS:[KEY_SCAN_CODE], AL

 

;        IN      AL, PORT_KBD_B                  ; ¦       0

;        OR      AL, 080H                        ; ¦

;        OUT     PORT_KBD_B, AL                  ; L----¬

;        IN      AL, PORT_KBD_B                  ;      ¦  1

;        AND     AL, 07FH                        ;      ¦

;        OUT     PORT_KBD_B, AL                  ; ------

;                                                ; ¦       0

        MOV     AL, EOI

        OUT     PORT_8259M, AL

        @POP    <EAX, DS>

        IRETD

KEYBOARD_HANDLER ENDP

 

timer.inc (Îáðàáîò÷èê ïðåðûâàíèÿ îò òàéìåðà)

 

;----------------------------------;

; Timer hardware interrupt handler ;

;----------------------------------;

 

TIMER_HANDLER PROC NEAR

        @PUSH   <DS, ES>

        PUSHAD

        MOV     AX, DS_DESC

        MOV     DS, AX

        MOV     AX, BIOS_DESC

        MOV     ES, AX

        INC     DWORD PTR ES:[06CH]             ; UPDATE BIOS TICK COUNTER

 

        MOV     AX, DS:[TIMER_CNT]              ; INTERNAL TICK COUNTER

        INC     AX

        CMP     AX, 9                           ; IS TIME FOR "*" OR " "?

        JNE     TIMER_END                       ; NO, IT ISN'T

 

        MOV     AX, TEXT_DESC

        MOV     ES, AX

        MOV     AL, ES:[2*79]

        MOV     BYTE PTR ES:[2*79], 0           ; " " <-> "*"

        CMP     AL, '*'

        JE      TIMER_FLAG

        MOV     BYTE PTR ES:[2*79], '*'         ; "*" <-> " "

 

TIMER_FLAG:

        XOR     AX, AX

TIMER_END:                                      ; UPDATE INTERNAL TICK COUNTER

        MOV     DS:[TIMER_CNT], AX

 

        MOV     AL, EOI

        OUT     PORT_8259M, AL                  ; ACKNOWLEDGE HANDLING OF INTERRUPT

 

; LOOKING FOR THE NEXT TASK BEING CONTINUED

 

        MOVZX   EAX, DS:[TASK_INDEX]

        ADD     DS:[TASK_INDEX], 2

        MOVZX   EAX, DS:[TASK_LIST+EAX]

        OR      EAX, EAX                        ; END OF TASK LIST?

        JNZ     TIMER_NEXT_TASK                 ; NOT END, RUNNING NEXT TASK

        MOVZX   EAX, DS:[TASK_LIST]

        MOV     DS:[TASK_INDEX], 2              ; END, RUNNING FIRST TASK

 

TIMER_NEXT_TASK:

        MOV     WORD PTR DS:[TASK_ADDR+4], AX   ; FAR POINTER TO TSS

 

        JMP     FWORD PTR DS:[TASK_ADDR]        ; SWITCH TO ANOTHER TASK :)

 

        POPAD

        @POP    <ES, DS>

        IRETD

TIMER_HANDLER ENDP

 

screenio.inc (Ðàáîòà ñ âèäåîêàðòîé)

 

;---------------------------------;

; Subroutines for screen text I/O ;

;---------------------------------;

 

; FUNCTION: CLEARS THE SCREEN

; IN:  NONE

; OUT: NONE, ALL REGS ARE SAVED

CLRSCR  PROC NEAR

        PUSH    ES

        PUSHAD

        MOV     AX, TEXT_DESC

        MOV     ES, AX

        XOR     EDI, EDI

        MOV     ECX, 80*25

        MOV     AX, 700H;1B00H

        REP     STOSW

        POPAD

        POP     ES

        RET

CLRSCR  ENDP

 

; FUNCTION: PRINTS THE EAX VALUE TO THE SCREEN

; IN:  EAX = 32-BIT VALUE, EDI = SCREEN OFFSET

; OUT: NONE, ALL REGS ARE SAVED

W_EAX   PROC NEAR

        @PUSH    <DS,ES>

        PUSHAD

        MOV     DX, DS_DESC

        MOV     DS, DX

        MOV     DX, TEXT_DESC

        MOV     ES, DX

        MOV     ECX, 8

        LEA     ESI, HEX_TAB

W_EAX_1:

        ROL     EAX, 4

        MOVZX   EBX, AL

        AND     BL, 0FH

        MOV     BL, DS:[ESI+EBX]

        MOV     ES:[EDI], BL

        ADD     EDI, 2

        LOOP    W_EAX_1

        POPAD

        @POP    <ES,DS>

        RET

W_EAX   ENDP

 

; FUNCTION: PRINTS ASCIIZ STRING TO THE SCREEN

; IN:  DS:ESI -> STRING, EDI = SCREEN OFFSET

; OUT: NONE, ALL REGS ARE SAVED

W_ASCIIZ PROC NEAR

        PUSH    ES

        PUSHAD

        MOV     AX, TEXT_DESC

        MOV     ES, AX

W_ASCIIZ_1:

        LODSB

        OR      AL, AL

        JZ      W_ASCIIZ_2

        STOSB

        INC     EDI

        JMP     W_ASCIIZ_1

W_ASCIIZ_2:

        POPAD

        POP     ES

        RET

W_ASCIIZ ENDP

 

service.inc (Ôîðìèðîâàíèå îáðàáîò÷èêà ïðåðûâàíèÿ)

 

;----------------------------------;

; SERVICE SOFTWARE INTERRUPT (30H) ;

;----------------------------------;

 

SERVICE_INTERRUPT PROC NEAR

        PUSHAD

        AND     EBX, 0FF00H                     ; BH = FUNCTION CODE

        SHR     EBX, 8

        CMP     EBX, 3

        JNC     SERV_INT_END                    ; ONLY 3 FUNCTIONS AVAILABLE

        SHL     EBX, 2                          ; ADDRESS OFFSET TABLE

        CALL    DWORD PTR CS:[FUNC_TAB+EBX]

SERV_INT_END:

        POPAD

        IRETD

 

F_00 LABEL NEAR

        JMP     CLRSCR                          ; CLEAR SCREEN

 

F_01 LABEL NEAR

        JMP     W_ASCIIZ                        ; OUT ASCIIZ STRING

 

F_02 LABEL NEAR

        JMP     W_EAX                           ; OUT 32-BIT EAX AS HEX

 

FUNC_TAB LABEL DWORD

        DD      F_00, F_01, F_02

SERVICE_INTERRUPT 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_DS.LIMIT, 0FFFFH            ; DATA SEGMENT HAS 64KB LIMIT

        MOV     GDT_SS.LIMIT, 0FFFFH            ; STACK SEGMENT HAS 64KB LIMIT

;        LGDT    FWORD PTR GDT_GDT               ; LOAD GDTR

 

        @JUMP                                   ; OVERLOAD CODE SELECTOR

        MOV     AX, DS_DESC

        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, SS_DESC

        MOV     SS, AX                          ; OVERLOAD STACK SELECTOR

 

        MOV     EAX, CR0

        AND     AL, 0FEH

        MOV     CR0, EAX                        ; BACK TO THE REAL MODE

 

        @JUMPR                                  ; RESTORE RM CODE SEGMENT

        MOV     AX, SSTACK

        MOV     SS, AX                          ; RESTORE RM STACK SEGMENT

        MOV     AX, DATA

        MOV     DS, AX                          ; RESTORE RM DATA SEGMENT

        MOV     ES, AX

        XOR     AX, AX

        MOV     FS, AX

        MOV     GS, AX

 

        MOV     IDTR.LIMIT, 3FFH                ; REAL MODE INTERRUPT TABLE SIZE

        MOV     DWORD PTR IDTR+2, 0             ; REAL MODE INTERRUPT TABLE ADDRESS

        LIDT    FWORD PTR IDTR                  ; LOAD REAL MODE INT TABLE

 

set_rm2.inc (Âîçâðàò â RealMode – ñïîñîá 2)

 

;--------------------------------;

; Sets Real Mode using CPU reset ;

; Works perfectly. :))           ;

;--------------------------------;

 

        MOV     ESP32, ESP

        MOV     AX, BIOS_DESC

        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    [DUMMY_IDT]

        INT     0

 

SHUTDOWN_RET    LABEL FAR

        MOV     AX, DATA

        MOV     DS, AX

        MOV     ES, AX

        MOV     AX, SSTACK

        MOV     SS, AX

        MOV     ESP, ESP32

        XOR     AX, AX

        MOV     FS, AX

        MOV     GS, AX

 

setupgdt.inc (Èíèöèàëèçàöèÿ GDT)

 

;-----------;

; Fills GDT ;

;-----------;

 

        MOV     AX, DATA

        MOV     DL, AH

        XOR     DH, DH

        SHL     AX, 4

        SHR     DX, 4

        MOV     SI, AX

        MOV     DI, DX

 

; GDT GOES HERE

 

        LEA     BX, GDT_GDT

        MOV     AX, SI

        MOV     DX, DI

        ADD     AX, OFFSET GDT

        ADC     DX, 0

        @SET_GDT_ENTRY

 

; 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_DS

        MOV     AX, SI

        MOV     DX, DI

        @SET_GDT_ENTRY

 

; STACK FOR 16/32 REAL/PROTECTED MODE MAIN TASK GOES HERE

 

        LEA     BX, GDT_SS

        MOV     AX, SS

        XOR     DH, DH

        MOV     DL, AH

        SHL     AX, 4

        SHR     DX, 4

        @SET_GDT_ENTRY

 

; 32-BIT PROTECTED MODE MAIN TASK CODE GOES HERE

 

        LEA     BX, GDT_CS32

        MOV     AX, CODE32

        XOR     DH, DH

        MOV     DL, AH

        SHL     AX, 4

        SHR     DX, 4

        @SET_GDT_ENTRY

        OR      [BX][S_DESC.ATTRIBS], 40H            ; 32-BIT STUFF

 

; IDT GOES HERE

 

        LEA     BX, GDT_IDT

        MOV     AX, SI

        MOV     DX, DI

        ADD     AX, OFFSET IDT

        ADC     DX, 0

        @SET_GDT_ENTRY

        MOV     IDTR.IDT_L, AX

        MOV     IDTR.IDT_H, DX

 

; TASKS' CODES GO HERE

 

        LEA     BX, GDT_CS_0

        MOV     AX, CODE_0

        XOR     DH, DH

        MOV     DL, AH

        SHL     AX, 4

        SHR     DX, 4

        @SET_GDT_ENTRY

        OR      [BX][S_DESC.ATTRIBS], 40H            ; 32-BIT STUFF

 

        LEA     BX, GDT_CS_1

        MOV     AX, CODE_1

        XOR     DH, DH

        MOV     DL, AH

        SHL     AX, 4

        SHR     DX, 4

        @SET_GDT_ENTRY

        OR      [BX][S_DESC.ATTRIBS], 40H            ; 32-BIT STUFF

 

; TASKS' STACKS GO HERE

 

        LEA     BX, GDT_SS_0

        MOV     AX, STCK_0

        XOR     DH, DH

        MOV     DL, AH

        SHL     AX, 4

        SHR     DX, 4

        @SET_GDT_ENTRY

 

        LEA     BX, GDT_SS_1

        MOV     AX, STCK_1

        XOR     DH, DH

        MOV     DL, AH

        SHL     AX, 4

        SHR     DX, 4

        @SET_GDT_ENTRY

 

; TSSs GO HERE

 

        LEA     BX, GDT_TSS_MAIN

        MOV     AX, SI

        MOV     DX, DI

        ADD     AX, OFFSET TSS_MAIN

        ADC     DX, 0

        @SET_GDT_ENTRY

 

        LEA     BX, GDT_TSS_0

        MOV     AX, SI

        MOV     DX, DI

        ADD     AX, OFFSET TSS_0

        ADC     DX, 0

        @SET_GDT_ENTRY

 

        LEA     BX, GDT_TSS_1

        MOV     AX, SI

        MOV     DX, DI

        ADD     AX, OFFSET TSS_1

        ADC     DX, 0

        @SET_GDT_ENTRY

 

setupidt.inc (Èíèöèàëèçàöèÿ IDT)

 

;-----------;

; Fills IDT ;

;-----------;

 

IRPC            N, 0123456789ABCDEF                     ; 00...0F

        LEA     EAX, EXC_0&N

        MOV     IDT_0&N.OFFS_L, AX

        SHR     EAX, 16

        MOV     IDT_0&N.OFFS_H, AX

ENDM

IRPC            N, 0123456789ABCDEF                     ; 10...1F

        LEA     EAX, EXC_1&N

        MOV     IDT_1&N.OFFS_L, AX

        SHR     EAX, 16

        MOV     IDT_1&N.OFFS_H, AX

ENDM

 

        LEA     EAX, TIMER_HANDLER                      ; 20

        MOV     IDT_TIMER.OFFS_L, AX

        SHR     EAX, 16

        MOV     IDT_TIMER.OFFS_H, AX

 

        LEA     EAX, KEYBOARD_HANDLER                   ; 21

        MOV     IDT_KEYBOARD.OFFS_L, AX

        SHR     EAX, 16

        MOV     IDT_KEYBOARD.OFFS_H, AX

 

IRPC            N, 234567                               ; 22...27

        LEA     EAX, DUMMY_IRET0

        MOV     IDT_2&N.OFFS_L, AX

        SHR     EAX, 16

        MOV     IDT_2&N.OFFS_H, AX

ENDM

IRPC            N, 89ABCDEF                             ; 28...2F

        LEA     EAX, DUMMY_IRET1

        MOV     IDT_2&N.OFFS_L, AX

        SHR     EAX, 16

        MOV     IDT_2&N.OFFS_H, AX

ENDM

 

        LEA     EAX, SERVICE_INTERRUPT                  ; 30

        MOV     IDT_SERVICE.OFFS_L, AX

        SHR     EAX, 16

        MOV     IDT_SERVICE.OFFS_H, AX

 

setuptss.inc (Ôîðìèðîâàíèå TSS)

 

;--------------------------------;

; Fills TSSs of additional tasks ;

;--------------------------------;

 

        OR      TSS_0.R_EFLAGS, 3200H           ; IOPL=3, ENABLED INTERRUPTS

        MOV     TSS_0.R_CS, CS_0_DESC

        MOV     TSS_0.R_EIP, OFFSET TASK_0

        MOV     TSS_0.R_SS, SS_0_DESC

        MOV     TSS_0.R_ESP, SIZE_STACK

        MOV     AX, 0

        MOV     TSS_0.R_DS, AX

        MOV     TSS_0.R_ES, AX

        MOV     TSS_0.R_FS, AX

        MOV     TSS_0.R_GS, AX

        MOV     TSS_0.SS0, SS_DESC

        MOV     TSS_0.ESP0, SIZE_STACK SHR 1

 

        OR      TSS_1.R_EFLAGS, 3200H           ; IOPL=3, ENABLED INTERRUPTS

        MOV     TSS_1.R_CS, CS_1_DESC

        MOV     TSS_1.R_EIP, OFFSET TASK_1

        MOV     TSS_1.R_SS, SS_1_DESC

        MOV     TSS_1.R_ESP, SIZE_STACK

        MOV     AX, 0

        MOV     TSS_1.R_DS, AX

        MOV     TSS_1.R_ES, AX

        MOV     TSS_1.R_FS, AX

        MOV     TSS_1.R_GS, AX

        MOV     TSS_1.SS0, SS_DESC

        MOV     TSS_1.ESP0, SIZE_STACK SHR 2

 

show_tss.inc (Ïðîñìîòð)

 

; IN: EAX = TSS OFFSET

SHOW_TSS PROC NEAR

        PUSH    DS

        PUSHAD

        MOV     EBX, EAX

        MOV     AX, DS_DESC

        MOV     DS, AX

 

        MOV     EDI, 10*80*2

        LEA     ESI, MSG_TSS

        LEA     EDX, OFFS_TSS

        MOV     ECX, 13

SHOW_TSS_CYCLE:

        CALL    W_ASCIIZ

        ADD     ESI, 32

 

        ADD     EBX, DS:[EDX]

        MOV     EAX, DS:[EBX]

        SUB     EBX, DS:[EDX]

        ADD     EDI, 7*2

        CALL    W_EAX

        ADD     EDX, 4

 

        ADD     EBX, DS:[EDX]

        MOV     EAX, DS:[EBX]

        SUB     EBX, DS:[EDX]

        ADD     EDI, 16*2

        CALL    W_EAX

        ADD     EDX, 4

 

        ADD     EDI, (80-7-16)*2

        LOOP    SHOW_TSS_CYCLE

        POPAD

        POP     DS

        RET

SHOW_TSS ENDP

 

tasks.inc (Îïèñàíèå çàäà÷)

 

;-----------------------------;

; 2 ADDITIONAL TASKS (RING 3) ;

;-----------------------------;

 

;----------------------;

; TASK #0 CODE SEGMENT ;

;----------------------;

 

CODE_0  SEGMENT PARA USE32

        ASSUME  CS:CODE_0

CS_0_BEGIN      =       $

TASK_0  PROC NEAR

        MOV     AX, DS_DESC

        MOV     DS, AX

        MOV     ES, AX

        LEA     ESI, MSG_TASK_0

        MOV     EDI, 5*80*2

        MOV     BH, 1

        INT     30H

        MOV     EAX, 0

        ADD     EDI, 80*2

TASK_0_L:

        MOV     BH, 2

        INT     30H

        INC     EAX

 

        MOV     EDX, EAX

 

        ADD     EDI, 80*2

        MOV     EAX, ESP

        MOV     BH, 2

        INT     30H                             ; VISUAL TEST OF ESP

 

        SUB     EDI, 80*2

        MOV     EAX, EDX

 

        JMP     TASK_0_L

TASK_0  ENDP

SIZE_CS_0       =       ($ - CS_0_BEGIN)

CODE_0  ENDS

 

;----------------------;

; TASK #1 CODE SEGMENT ;

;----------------------;

 

CODE_1  SEGMENT PARA USE32

        ASSUME  CS:CODE_1

CS_1_BEGIN      =       $

TASK_1  PROC NEAR

        MOV     AX, DS_DESC

        MOV     DS, AX

        MOV     ES, AX

        LEA     ESI, MSG_TASK_1

        MOV     EDI, 5*80*2+10*2

        MOV     BH, 1

        INT     30H

        MOV     EAX, -1

        ADD     EDI, 80*2

TASK_1_L:

        MOV     BH, 2

        INT     30H

        DEC     EAX

 

        MOV     EDX, EAX

 

        ADD     EDI, 80*2

        MOV     EAX, ESP

        MOV     BH, 2

        INT     30H                             ; VISUAL TEST OF ESP

 

        SUB     EDI, 80*2

        MOV     EAX, EDX

 

        JMP     TASK_1_L

TASK_1  ENDP

SIZE_CS_1       =       ($ - CS_1_BEGIN)

CODE_1  ENDS

 

;-----------------------;

; TASK #0 STACK SEGMENT ;

;-----------------------;

 

STCK_0  SEGMENT PARA

        DB      SIZE_STACK DUP (?)

STCK_0  ENDS

 

;-----------------------;

; TASK #1 STACK SEGMENT ;

;-----------------------;

 

STCK_1  SEGMENT PARA

        DB      SIZE_STACK DUP (?)

STCK_1  ENDS

 

exc.inc

 

;----------------------;

; Exception handler(s) ;

;----------------------;

 

M       =       0

IRPC            N, 0123456789ABCDEF

EXC_0&N LABEL WORD

        CLI

        PUSH            EBP

        MOV             EBP, ESP

        PUSHAD

        MOV             EAX, M

        M       =       M+1

        JMP             EXC_HANDLER

ENDM

 

M       =       010H

IRPC            N, 0123456789ABCDEF

EXC_1&N LABEL WORD

        CLI

        PUSH            EBP

        MOV             EBP, ESP

        PUSHAD

        MOV             EAX, M

        M       =       M+1

        JMP             EXC_HANDLER

ENDM

 

EXC_HANDLER     PROC    NEAR

        PUSH    DS

 

        MOV     BX, DS_DESC

        MOV     DS, BX

 

;        CALL    CLRSCR

        LEA     ESI, MSG_EXC

        MOV     EDI, 40*2

        CALL    W_ASCIIZ                        ; "EXCEPTION: "

        ADD     EDI, 11*2

        CALL    W_EAX                           ; EXCEPTION NUMBER

        SUB     EDI, 11*2

 

        MOV     EBX, EBP

        ADD     EBX, 4                          ; EBX = ^CS:EIP

 

        MOVZX   EAX, BYTE PTR DS:[EXC_ERR+EAX]

        OR      EAX, EAX

        JZ      EXC_HANDLER_NO_ERR_CODE         ; THE EXCEPTION HAS NO ERROR CODE

 

        ADD     EBX, 4                          ; CORRECT EBX

 

        LEA     ESI, MSG_EXC_ERR

        ADD     EDI, 80*2

        CALL    W_ASCIIZ                        ; "ERROR CODE: "

 

        MOV     EAX, SS:[EBP+4]

        AND     EAX, 0FFFFH

        ADD     EDI, 12*2

        CALL    W_EAX

        SUB     EDI, 12*2

        SUB     EDI, 80*2

 

EXC_HANDLER_NO_ERR_CODE:

        LEA     ESI, MSG_CSEIP

        ADD     EDI, 2*80*2

        CALL    W_ASCIIZ                        ; "CS=XXXXXXXX EIP=XXXXXXXX"

        ADD     EDI, 3*2

        MOVZX   EAX, WORD PTR SS:[EBX+4]

        CALL    W_EAX                           ; CS

        ADD     EDI, 13*2

        MOV     EAX, SS:[EBX]

        CALL    W_EAX                           ; EIP

        SUB     EDI, (3+13)*2

 

;        jmp     $                               ; INFINITE LOOP

 

        MOV     AX, SS_DESC

        MOV     SS, AX

        MOV     ESP, DS:[ESP32]

        @RETF

 

        IRETD

EXC_HANDLER     ENDP