Listing 1 dostest.asm

page ,132

; masm tisr ; >err
   .286p
.xlist
include ..\..\include\bogus.inc
.list

Words struc
LoWord dw ?
HiWord dw ?
Words ends

EOI equ 020h             ; EOI command for PIC

INTA00 equ 020h          ; Master PIC control
INTA01 equ 021h          ; Master PIC mask register
INT_MASTER_0 equ 08h         ; Master PIC INT number

INTB00 equ 0A0h          ; Slave PIC control
INTB01 equ 0A1h          ; Slave PIC mask register
INT_SLAVE_0 EQU 70h      ; Slave PIC INT number

;
; Set variables for our interrupt number
;
ife (FAKE_IRQ GE 8)
INT_DEV equ (INT_MASTER_0+(FAKE_IRQ AND 7))
PIC00 equ INTA00
PIC01 equ INTA01
else
INT_DEV equ (INT_SLAVE_0+(FAKE_IRQ AND 7))
INT_MASK equ 1 SHL (FAKE_IRQ AND 7)
PIC00 equ INTB00
PIC01 equ INTB01
endif

page
CONST SEGMENT DWORD PUBLIC 'DATA'
sdNoBogus db 'I do not see the bogus device.',0dh,0ah,'$'
sdPrompt db 0DH,0Ah,'S)tart, or Q)uit: ','$'
sdCRLF  db 0Dh,0Ah,'$'
sdDot   db '.','$'

CONST ENDS

DATA SEGMENT DWORD PUBLIC 'DATA'
dwCount1 dw 0
dwCount2 dw 0
1pPrevISR dd 0          ; address of prior ISR
fStopping db 0          ; TRUE when stopping
DATA ENDS

STACK SEGMENT DWORD STACK 'STACK'
   db 512 dup (?)
STACK ENDS

DGroup GROUP CONST,DATA,STACK

page

;IP IntSvcRtn - The Interrupt Service Routine
;
;   WARNINGS
;
;   NOTES
;       This ISR generally increments an interrupt count (dwCount1)
;       and re-arms the device.
;
;       If the "fStopping" flag is set, the device is not re-armed.
;

FIXED_TEXT SEGMENT PARA PUBLIC 'CODE'
segData1    dw DGroup
   assume  CS:FIXED_TEXT,DS:NOTHING
IntSvcRtn proc far
    push    ax
    push    dx
    push    ds
    mov ds,segData1
    assume  ds:DGroup
    inc dwCount1
    mov al,NOT FAKE_CTL_EOI
    mov dx,FAKE_PORT
    out dx,al           ; send EOI to device
    mov al,EOI
    out PIC00,al        ; send EOI to PIC
ife (PIC00 EQ INTA00)
    out INTA00,al       ; send EOI to master PIC, too

endif
    cmp fStopping,0     ; exiting?
    jnz isr9            ; if so, then don't restart
    mov al,NOT FAKE_CTL_START
    mov dx,FAKE_PORT
    out dx,al           ; restart I/O
isr9:
    pop ds
    assume  ds:NOTHING
    pop dx
    pop ax
    iret
IntSvcRtn endp

FIXED_TEXT ENDS

page
;IP __main - program entry point
;
;   NOTES
;       The user is prompted to S)tart or Q)uit the program. If
;       "S" is selected, the programs enables interrupts and arms
;       the device, printing out a dot each time the device interrupts.
;

_TEXT SEGMENT PARA PUBLIC 'CODE'
segData2    dw  DGroup
segFixed    dw  FIXED_TEXT
    assume cs:_TEXT,ds:NOTHING

__main label far
    mov ds,segData2    ; Initialize default data segment
    assume    ds:DGroup

    mov dx,FAKE_PORT
    in  al,dx          ; Is the bogus device present ?
    or  al,al
    jns ml0        ; skip if so
    mov dx,OFFSET DGroup:sdNoBogus
    mov ah,9
    int 21h         ; else print error message
    mov ax,4C01h
    int 21h         ; and exit

ml0:
    mov ax,3500h+INT_DEV
    cli
    int 21h         ; Query the current ISR
    mov lpPrevISR.LoWord,bx
    mov lpPrevISR.HiWord,es  ; Save it

    mov dx,OFFSET FIXED_TEXT:IntSvcRtn
    push    ds
    mov ds,segFixed
    assume  ds:NOTHING
    mov ax,2500h+INT_DEV
    int 21h         ; Set our ISR
    pop ds
    assume  ds:DGroup
    sti

    mov dx,OFFSET DGroup:sdPrompt
    mov ah,9
    int 21h         ; "S)tart or Q)uit

ml1:
    mov dl,OFFh
    mov ah,6
    int 21h         ; read from console, nowait
    jz  ml3
    or  al,40h
    cmp al,'q'
    je  ml8         ; skip if "Q" pressed
    cmp al,'s'
    jne ml3         ; skip if "S" not pressed
    cli
    in  al,PIC01        ; unmask the interrupt
    and al,NOT INT_MASK
    out PIC01,al
    sti
    mov al,NOT FAKE_CTL_START
    mov dx,FAKE_PORT
    out dx,al           ; start device I/O
ml3:
    mov ax,dwCount1
    cmp ax,dwCount2
    je  ml4         ; skip if the count of interrupts unchanged
    mov dwCount2,ax
    mov dx,OFFSET DGroup:sdDot
    mov ah,9
    int 21h         ; else, display a dot
ml4:
    jmp ml1         ; loop for more
    
ml8:
    mov fStopping,1     ; Tell the ISR to stop
    mov dx,FAKE_PORT
ml9:
    in  al,dx
    rcr al,1
    jnc m19          ; loop while busy

    cli
    in  al,PIC01
    or  al,INT_MASK
    out PIC01,al         ; mask the interrupt level
    sti

    push    ds
    lds dx,lpPrevISR
    assume  ds:NOTHING
    mov ax,2500h+INT_DEV
    int 21h         ; restore the previous ISR
    pop ds
    assume  ds:DGroup
    mov ax,4C00h
    int 21h         ; exit
_TEXT ENDS

    end _main
; End of File