Category : System Diagnostics for your computer
Archive   : ATIM.ZIP
Filename : ATIM.ASM

 
Output of file : ATIM.ASM contained in archive : ATIM.ZIP
; 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


  3 Responses to “Category : System Diagnostics for your computer
Archive   : ATIM.ZIP
Filename : ATIM.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/