⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _pmdos.asm

📁 AT91RM9200的完整启动代码:包括loader, boot及U-boot三部分均已编译通过!欢迎下载使用!
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;****************************************************************************
;*
;*                  SciTech OS Portability Manager Library
;*
;*  ========================================================================
;*
;*    The contents of this file are subject to the SciTech MGL Public
;*    License Version 1.0 (the "License"); you may not use this file
;*    except in compliance with the License. You may obtain a copy of
;*    the License at http://www.scitechsoft.com/mgl-license.txt
;*
;*    Software distributed under the License is distributed on an
;*    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
;*    implied. See the License for the specific language governing
;*    rights and limitations under the License.
;*
;*    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
;*
;*    The Initial Developer of the Original Code is SciTech Software, Inc.
;*    All Rights Reserved.
;*
;*  ========================================================================
;*
;* Language:    80386 Assembler, TASM 4.0 or NASM
;* Environment: IBM PC Real mode and 16/32 bit protected mode
;*
;* Description: Low level assembly support for the PM library specific to
;*              MSDOS interrupt handling.
;*
;****************************************************************************

        IDEAL

include "scitech.mac"           ; Memory model macros

header      _pmdos              ; Set up memory model

; Define the size of our local stacks. For real mode code they cant be
; that big, but for 32 bit protected mode code we can make them nice and
; large so that complex C functions can be used.

ifdef flatmodel
MOUSE_STACK EQU 4096
TIMER_STACK EQU 4096
KEY_STACK   EQU 1024
INT10_STACK EQU 1024
IRQ_STACK   EQU 1024
else
MOUSE_STACK EQU 1024
TIMER_STACK EQU 512
KEY_STACK   EQU 256
INT10_STACK EQU 256
IRQ_STACK   EQU 256
endif

ifdef   USE_NASM

; Macro to load DS and ES registers with correct value.

%imacro   LOAD_DS 0
%ifdef  flatmodel
        mov     ds,[cs:_PM_savedDS]
        mov     es,[cs:_PM_savedDS]
%else
        push    ax
        mov     ax,_DATA
        mov     ds,ax
        pop     ax
%endif
%endmacro

; Note that interrupts we disable interrupts during the following stack
; %imacro for correct operation, but we do not enable them again. Normally
; these %imacros are used within interrupt handlers so interrupts should
; already be off. We turn them back on explicitly later if the user code
; needs them to be back on.

; Macro to switch to a new local stack.

%imacro NEWSTK  1
        cli
        mov     [seg_%1],ss
        mov     [ptr_%1],_sp
        mov     [TempSeg],ds
        mov     ss,[TempSeg]
        mov     _sp,offset %1
%endmacro

; %imacro to switch back to the old stack.

%imacro   RESTSTK   1
        cli
        mov     ss,[seg_%1]
        mov     _sp,[ptr_%1]
%endmacro

; %imacro to swap the current stack with the one saved away.

%imacro SWAPSTK 1
        cli
        mov     ax,ss
        xchg    ax,[seg_%1]
        mov     ss,ax
        xchg    _sp,[ptr_%1]
%endmacro

else

; Macro to load DS and ES registers with correct value.

MACRO   LOAD_DS
ifdef   flatmodel
        mov     ds,[cs:_PM_savedDS]
        mov     es,[cs:_PM_savedDS]
else
        push    ax
        mov     ax,_DATA
        mov     ds,ax
        pop     ax
endif
ENDM

; Note that interrupts we disable interrupts during the following stack
; macro for correct operation, but we do not enable them again. Normally
; these macros are used within interrupt handlers so interrupts should
; already be off. We turn them back on explicitly later if the user code
; needs them to be back on.

; Macro to switch to a new local stack.

MACRO   NEWSTK  stkname
        cli
        mov     [seg_&stkname&],ss
        mov     [ptr_&stkname&],_sp
        mov     [TempSeg],ds
        mov     ss,[TempSeg]
        mov     _sp,offset stkname
ENDM

; Macro to switch back to the old stack.

MACRO   RESTSTK stkname
        cli
        mov     ss,[seg_&stkname&]
        mov     _sp,[ptr_&stkname&]
ENDM

; Macro to swap the current stack with the one saved away.

MACRO   SWAPSTK stkname
        cli
        mov     ax,ss
        xchg    ax,[seg_&stkname&]
        mov     ss,ax
        xchg    _sp,[ptr_&stkname&]
ENDM

endif

begdataseg  _pmdos

ifdef flatmodel
    cextern _PM_savedDS,USHORT
endif
    cextern _PM_critHandler,CPTR
    cextern _PM_breakHandler,CPTR
    cextern _PM_timerHandler,CPTR
    cextern _PM_rtcHandler,CPTR
    cextern _PM_keyHandler,CPTR
    cextern _PM_key15Handler,CPTR
    cextern _PM_mouseHandler,CPTR
    cextern _PM_int10Handler,CPTR

    cextern _PM_ctrlCPtr,DPTR
    cextern _PM_ctrlBPtr,DPTR
    cextern _PM_critPtr,DPTR

    cextern _PM_prevTimer,FCPTR
    cextern _PM_prevRTC,FCPTR
    cextern _PM_prevKey,FCPTR
    cextern _PM_prevKey15,FCPTR
    cextern _PM_prevBreak,FCPTR
    cextern _PM_prevCtrlC,FCPTR
    cextern _PM_prevCritical,FCPTR
    cextern _PM_prevRealTimer,ULONG
    cextern _PM_prevRealRTC,ULONG
    cextern _PM_prevRealKey,ULONG
    cextern _PM_prevRealKey15,ULONG
    cextern _PM_prevRealInt10,ULONG

cpublic _PM_pmdosDataStart

; Allocate space for all of the local stacks that we need. These stacks
; are not very large, but should be large enough for most purposes
; (generally you want to handle these interrupts quickly, simply storing
; the information for later and then returning). If you need bigger
; stacks then change the appropriate value in here.

            ALIGN   4
            dclb MOUSE_STACK    ; Space for local stack (small)
MsStack:                        ; Stack starts at end!
ptr_MsStack DUINT   0           ; Place to store old stack offset
seg_MsStack dw      0           ; Place to store old stack segment

            ALIGN   4
            dclb INT10_STACK    ; Space for local stack (small)
Int10Stack:                     ; Stack starts at end!
ptr_Int10Stack  DUINT   0       ; Place to store old stack offset
seg_Int10Stack  dw      0       ; Place to store old stack segment

            ALIGN   4
            dclb TIMER_STACK    ; Space for local stack (small)
TmStack:                        ; Stack starts at end!
ptr_TmStack DUINT   0           ; Place to store old stack offset
seg_TmStack dw      0           ; Place to store old stack segment

            ALIGN   4
            dclb TIMER_STACK    ; Space for local stack (small)
RtcStack:                       ; Stack starts at end!
ptr_RtcStack DUINT  0           ; Place to store old stack offset
seg_RtcStack dw     0           ; Place to store old stack segment
RtcInside   dw      0           ; Are we still handling current interrupt

            ALIGN   4
            dclb KEY_STACK      ; Space for local stack (small)
KyStack:                        ; Stack starts at end!
ptr_KyStack DUINT   0           ; Place to store old stack offset
seg_KyStack dw      0           ; Place to store old stack segment
KyInside    dw      0           ; Are we still handling current interrupt

            ALIGN   4
            dclb KEY_STACK      ; Space for local stack (small)
Ky15Stack:                      ; Stack starts at end!
ptr_Ky15Stack   DUINT   0       ; Place to store old stack offset
seg_Ky15Stack   dw      0       ; Place to store old stack segment

TempSeg     dw      0           ; Place to store stack segment

cpublic _PM_pmdosDataEnd

enddataseg  _pmdos

begcodeseg  _pmdos              ; Start of code segment

cpublic _PM_pmdosCodeStart

;----------------------------------------------------------------------------
; PM_mouseISR - Mouse interrupt subroutine dispatcher
;----------------------------------------------------------------------------
; Interrupt subroutine called by the mouse driver upon interrupts, to
; dispatch control to high level C based subroutines. Interrupts are on
; when we call the user code.
;
; It is _extremely_ important to save the state of the extended registers
; as these may well be trashed by the routines called from here and not
; restored correctly by the mouse interface module.
;
; NOTE: This routine switches to a local stack before calling any C code,
;       and hence is _not_ re-entrant. For mouse handlers this is not a
;       problem, as the mouse driver arbitrates calls to the user mouse
;       handler for us.
;
; Entry:    AX  - Condition mask giving reason for call
;           BX  - Mouse button state
;           CX  - Horizontal cursor coordinate
;           DX  - Vertical cursor coordinate
;           SI  - Horizontal mickey value
;           DI  - Vertical mickey value
;
;----------------------------------------------------------------------------
ifdef   DJGPP
cprocstart  _PM_mouseISR
else
cprocfar    _PM_mouseISR
endif

        push    ds              ; Save value of DS
        push    es
        pushad                  ; Save _all_ extended registers
        cld                     ; Clear direction flag

        LOAD_DS                 ; Load DS register
        NEWSTK  MsStack         ; Switch to local stack

; Call the installed high level C code routine

        clrhi   dx              ; Clear out high order values
        clrhi   cx
        clrhi   bx
        clrhi   ax
        sgnhi   si
        sgnhi   di

        push    _di
        push    _si
        push    _dx
        push    _cx
        push    _bx
        push    _ax
        sti                     ; Enable interrupts
        call    [CPTR _PM_mouseHandler]
        _add    sp,12,24

        RESTSTK MsStack         ; Restore previous stack

        popad                   ; Restore all extended registers
        pop     es
        pop     ds
        ret                     ; We are done!!

cprocend

;----------------------------------------------------------------------------
; PM_timerISR - Timer interrupt subroutine dispatcher
;----------------------------------------------------------------------------
; Hardware interrupt handler for the timer interrupt, to dispatch control
; to high level C based subroutines. We save the state of all registers
; in this routine, and switch to a local stack. Interrupts are *off*
; when we call the user code.
;
; NOTE: This routine switches to a local stack before calling any C code,
;       and hence is _not_ re-entrant. Make sure your C code executes as
;       quickly as possible, since a timer overrun will simply hang the
;       system.
;----------------------------------------------------------------------------
cprocfar    _PM_timerISR

        push    ds              ; Save value of DS
        push    es
        pushad                  ; Save _all_ extended registers
        cld                     ; Clear direction flag

        LOAD_DS                 ; Load DS register

        NEWSTK  TmStack         ; Switch to local stack
        call    [CPTR _PM_timerHandler]
        RESTSTK TmStack         ; Restore previous stack

        popad                   ; Restore all extended registers
        pop     es
        pop     ds
        iret                    ; Return from interrupt

cprocend

;----------------------------------------------------------------------------
; PM_chainPrevTimer - Chain to previous timer interrupt and return
;----------------------------------------------------------------------------
; Chains to the previous timer interrupt routine and returns control
; back to the high level interrupt handler.
;----------------------------------------------------------------------------
cprocstart  PM_chainPrevTimer

ifdef   TNT
        push    eax
        push    ebx
        push    ecx
        pushfd                  ; Push flags on stack to simulate interrupt
        mov     ax,250Eh        ; Call real mode procedure function
        mov     ebx,[_PM_prevRealTimer]
        mov     ecx,1           ; Copy real mode flags to real mode stack
        int     21h             ; Call the real mode code
        popfd
        pop     ecx
        pop     ebx
        pop     eax
        ret
else
        SWAPSTK TmStack         ; Swap back to previous stack

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -