home *** CD-ROM | disk | FTP | other *** search
- ; atim.asm ibm-at high res program timer
- ; by Howard Vigorita, NYACC
- ;-----------------------------------------------------
-
- false equ 0
- true equ NOT false
-
- CCPM equ false ; set FALSE to use back door COMMAND.COM entry
- ; set TRUE if no support for INT 2Eh
- CLONE equ false ; set FALSE if a true blue IBM PC-AT or set
- ; TRUE if bios doesn't shut off timer
-
- cr equ 0Dh
- lf equ 0Ah
-
- dos equ 21h
-
- ; help simplify the coding
- ;
- bpt equ BYTE PTR
- wpt equ WORD PTR
- jmps macro x
- jmp short x
- endm
-
- ; set up as a COM file
- ;
- code SEGMENT word PUBLIC 'CODE'
- assume cs:code, ds:code
- tos equ $ ; top of segment used to make constants
-
-
- ; fields of interest in program segment prefix
- ;
- ORG 2Ch
- env_seg dw ? ; segment where environment located
- ORG 80h
- dta equ $ ; default disk transfer area
- len db ?
- str db ?
- prog db ?
-
- ORG 100h
-
- at_timer:
- jmp start
-
- time_lo dw 0
- time_hi dw 0
- i70jmp dd ?
-
- sp_sav dw ?
- IF NOT CCPM
- buffer db 10 dup (?)
- ENDIF
-
- secs db ' seconds', CR, LF, '$'
- msg db CR,LF,'Elapsed Time: $'
-
- IF CCPM
- srch_str db 'COMSPEC='
- srch_len equ $-srch_str
-
- program db 'command.com',0
- db 20 dup(?)
- param_block label word
- dw 0
- dw offset cmd_buf
- p1 dw ?
- dw -1
- p2 dw ?
- dw -1
- p3 dw ?
- cmd_buf db 2
- db ' '
- cmd_txt db '/c'
- buffer db 80 dup(?)
- ENDIF
-
- main proc near
-
- start:
-
- IF CCPM
- ; copy command line
- ;
- xor BX,BX
- mov BL,len
- or BL,BL
- jnz cmd_ok
- jmp exit
- cmd_ok:
- dec BX
- mov CX,BX
- mov DI,offset prog
- inc BX
- set_zb:
- mov bpt str[BX],0
- add cmd_buf,CL
- or CL,CL
- jbe free_mem ; no command tail
-
- ; transfer bal of line to exec cmd buffer
- ;
- inc CL
- mov SI,DI
- mov DI,offset cmd_txt+2
- rep movsb
- add cmd_buf,1
- ENDIF
-
- ; free up system memory for child
- ;
- free_mem:
- mov BX,(byt_cnt+15) shr 4 ; paragraphs of code
- mov AH,4Ah ; shrink allocation
- int dos
- jnc sav_stack ; bail out if allocation error
- jmp exit
- sav_stack:
- mov sp_sav,SP
-
- IF CCPM
- ; search environment for comspec
- ;
- srch_env:
- push CS ; save ES
- mov ES,env_seg ; point ES @ environment segment
- xor DI,DI ; point DI to environment base
- mov SI,offset srch_str ; point SI to search string
- mov CX,srch_len ; length of search string
- mov AX,DI ; clear AL for later null scan
- mov BX,SI ; save pointer to search string
- mov DX,CX ; save search length
- srch_lp:
- cmp bpt ES:[DI],0 ; environment end?
- je srch_x ; if so, exit
- mov CX,DX ; restore search length
- mov SI,BX ; restore search pointer
- repe cmpsb ; do block compare
- je mov_comspec ; if ZF set, found it
- not CX ; else, make CX a big number
- repne scasb ; and scan to end of string (null)
- jmps srch_lp ; do it again
-
- mov_comspec:
- mov BX,DI ; save pointer to comspec
- not CX ; change CX from 0 to FFFFh
- repne scasb ; and scan for end of string marker
- not CX ; CX = length of comspec
- mov DI,offset program
- mov SI,BX ; comspec now source
- mov DX,DS ; exchange ES & DS
- mov AX,ES
- mov DS,AX
- mov ES,DX
- rep movsb ; block copy compsec from environment
- mov DS,DX ; restore DS
-
- srch_x:
- pop ES ; restore ES
- ENDIF
-
- load_exec:
- cli
- call init_70 ; jiggle the controller
- call disable_70
- call init_70 ; turn on hi res timer
-
- IF CCPM
- mov AX,CS
- mov p1,AX
- mov p2,AX
- mov p3,AX
- mov DX,offset program
- mov BX,offset param_block
- mov sp_sav,SP
- mov AX,4B00h ; load & execute function
- sti
- int dos
- ELSE
- mov SI,offset dta ; point to command in default dta
- sti ; interrupts on
- int 2Eh ; back door into COMMAND.COM
- ENDIF
-
- cli ; interrupts off till stack back
-
- ; restore registers & stack
- ;
- mov CX,CS
- mov SS,CX
- mov SP,CS:sp_sav
- mov DS,CX
- mov ES,CX
-
- call disable_70 ; shut off hi res timer
- sti ; allow interrupts again
-
- mov DX,offset msg
- mov AH,9
- int dos
- mov DI,offset buffer
- mov BX,time_lo
- call bin_2_dec
-
- exit:
- mov AH,4Ch
- int dos
-
- main endp
-
- ; convert binary word to ascii decimal & write it in buffer
- ; uses the 8086 divide instruction
- ; parameters passed in registres as follows:
- ; AL leading 0 fill character (usually 0 or space)
- ; BX binary word to be converted
- ; CX decimal digit limit (NTE 5)
- ; DX (not preserved)
- ; SI (not preserved)
- ; DI address of buffer to put ascii decimals into
- bin_2_dec proc near
-
- mov CX,7
- mov AL,'0'
- push CX
- rep stosb ; block fill, DI += CX
- mov bpt [DI],'$'
- mov bpt [DI-4],'.'
- mov bpt [DI-6],' '
- mov bpt [DI-7],' '
- mov AX,BX ; put binary word into AX
- mov SI,10 ; put divisor in SI
- pop CX
- inc CX
-
- next_digit:
- dec CX
- jz bin_2_dec_x
- xor DX,DX ; clear dividend high word
- div SI ; AX = (DX:AX)/SI, DX = remainder
- add DX,'0' ; convert DL remainder byte to ascii
- dec DI ; back step in buffer
- mov byte ptr [DI], DL ; put character there
- cmp CX,5
- jne cont
- dec DI
- cont:
- or AX,AX ; all done? (AX = 0?)
- jnz next_digit ; if not, do another digit
- bin_2_dec_x:
- mov DX,offset buffer
- mov AH,9
- int dos
- mov DX,offset secs
- mov AH,9
- int dos
- ret
- bin_2_dec endp
-
-
- ; initialize interrupt vector table
- ;
- init_70 proc near
- mov AH,2
- int 1Ah
- mov AH,3
- int 1Ah
- mov AX,3570h ; get interrupt 70h vectors
- int dos
- mov wpt i70jmp,BX ; save them
- mov wpt i70jmp+2,ES
- push CS ; restore ES
- pop ES
- mov dx,offset int_70
- mov ax,2570h ; put new int_70 handler in table
- cli
- int dos
- call enable_int ; enable int_70
- cli ; but shut it off for now
- ret
- init_70 endp
-
- ; enable the high relolution timer
- ;
- enable_int proc near
- cli
- mov AL,0Bh
- out 70h,AL
- jmp $+2
- in AL,71h
- or AL,01000000b ; disable bit 6
- mov AH,AL
- mov AL,0Bh
- out 70h,AL
- jmp $+2
- mov AL,AH
- out 71h,AL
- in AL,0A1h
- and AL,11111110b ; disable bit 0
- out 0A1h,AL
- mov AL,20h
- out 0A0h,AL
- out 020h,AL
- sti
- ret
- enable_int endp
-
- ; disable timer and repair interrupt vector table
- ;
- disable_70 proc near
- cli
- push DS
- mov DX,wpt i70jmp ; get old int 70 vectors
- mov DS,wpt i70jmp+2
- mov ax,2570h ; restore them
- int dos
- pop DS
- mov AL,0Bh
- out 70h,AL
- jmp $+2
- in AL,71h
- and AL,10111111b ; enable bit 6
- mov AH,AL
- mov AL,0Bh
- out 70h,AL
- jmp $+2
- mov AL,AH
- out 71h,AL
- in AL,0A1h
- or AL,00000001b ; enable bit 0
- out 0A1h,AL
- mov AL,20h
- out 0A0h,AL
- out 020h,AL
- sti
-
- ; convert 1024 ticks/sec count to 1000 ticks/sec
- ;
- dec_cnvt:
- mov CX,time_lo
- dec_lp:
- sub CX,1024
- jbe dec_lp_x
- sub time_lo,24
- jmps dec_lp
- dec_lp_x:
- add CX,1024
- cmp CX,768
- jbe b_768
- sub time_lo,6*3
- jmps disable_x
- b_768:
- cmp CX,512
- jbe b_512
- sub time_lo,6*2
- jmps disable_x
- b_512:
- cmp CX,256
- jbe disable_x
- sub time_lo,6
- disable_x:
- ret
- disable_70 endp
-
- ; high resolution timer interrupt handler
- ;
- EVEN
- int_70 proc far
- push AX ; save registers used
- push DS
- mov AX,CS
- mov DS,AX ; point data segment to code segment
- assume DS:code
- inc time_lo ; bump counters
- adc time_hi,0
- pushf ; prepare to 'call' original INT 70h
- call i70jmp ; call & iret back here
- IF NOT CLONE
- call enable_int ; if bios shuts timer off, turn it back on
- ENDIF
- pop DS ; restore registers used
- pop AX
- iret
- int_70 endp
-
- last_byte equ $
- byt_cnt equ offset last_byte-tos
-
- code ends
- end at_timer
-