home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / at / atim.arc / ATIM.ASM next >
Encoding:
Assembly Source File  |  1986-12-28  |  7.2 KB  |  392 lines

  1.     ;    atim.asm    ibm-at high res program timer
  2.     ;            by Howard Vigorita, NYACC
  3.     ;-----------------------------------------------------
  4.  
  5. false    equ    0
  6. true    equ    NOT false
  7.  
  8. CCPM    equ    false        ; set FALSE to use back door COMMAND.COM entry
  9.                 ;   set TRUE if no support for INT 2Eh
  10. CLONE    equ    false        ; set FALSE if a true blue IBM PC-AT or set
  11.                 ;   TRUE if bios doesn't shut off timer
  12.  
  13. cr    equ    0Dh
  14. lf    equ    0Ah
  15.  
  16. dos    equ    21h
  17.  
  18.     ; help simplify the coding
  19.     ;
  20. bpt    equ    BYTE PTR
  21. wpt    equ    WORD PTR
  22. jmps     macro    x
  23.     jmp short x
  24.      endm
  25.  
  26.     ; set up as a COM file
  27.     ;
  28. code    SEGMENT word PUBLIC 'CODE'
  29.     assume    cs:code, ds:code
  30. tos    equ    $            ; top of segment used to make constants
  31.  
  32.  
  33.     ; fields of interest in program segment prefix
  34.     ;
  35.     ORG    2Ch
  36. env_seg    dw    ?            ; segment where environment located
  37.     ORG    80h
  38. dta    equ    $            ; default disk transfer area
  39. len    db    ?
  40. str    db    ?
  41. prog    db    ?
  42.  
  43.     ORG    100h
  44.  
  45. at_timer:
  46.     jmp    start
  47.  
  48. time_lo        dw    0
  49. time_hi        dw    0
  50. i70jmp        dd    ?
  51.  
  52. sp_sav        dw    ?
  53.      IF NOT CCPM
  54. buffer        db 10 dup (?)
  55.      ENDIF
  56.  
  57. secs    db    ' seconds', CR, LF, '$'
  58. msg    db    CR,LF,'Elapsed Time: $'
  59.  
  60.      IF CCPM
  61. srch_str    db    'COMSPEC='
  62. srch_len    equ    $-srch_str
  63.  
  64. program        db    'command.com',0
  65.         db    20 dup(?)
  66. param_block    label    word
  67.         dw    0
  68.         dw    offset cmd_buf
  69. p1        dw    ?
  70.         dw    -1
  71. p2        dw    ?
  72.         dw    -1
  73. p3        dw    ?
  74. cmd_buf        db    2
  75.         db    ' '
  76. cmd_txt        db    '/c'
  77. buffer        db    80 dup(?)
  78.      ENDIF
  79.  
  80. main    proc    near
  81.  
  82. start:
  83.  
  84.      IF CCPM
  85.     ;    copy command line
  86.     ;
  87.     xor    BX,BX
  88.     mov    BL,len
  89.     or    BL,BL
  90.     jnz    cmd_ok
  91.     jmp    exit
  92. cmd_ok:
  93.     dec    BX
  94.     mov    CX,BX
  95.     mov    DI,offset prog
  96.     inc    BX
  97. set_zb:
  98.     mov    bpt str[BX],0
  99.     add    cmd_buf,CL
  100.     or    CL,CL
  101.     jbe    free_mem        ; no command tail
  102.  
  103.     ; transfer bal of line to exec cmd buffer
  104.     ;
  105.     inc    CL
  106.     mov    SI,DI
  107.     mov    DI,offset cmd_txt+2
  108.     rep    movsb
  109.     add    cmd_buf,1
  110.      ENDIF
  111.  
  112.     ; free up system memory for child
  113.     ;
  114. free_mem:
  115.     mov    BX,(byt_cnt+15) shr 4    ; paragraphs of code
  116.     mov    AH,4Ah            ; shrink allocation
  117.     int    dos
  118.     jnc    sav_stack        ; bail out if allocation error
  119.     jmp    exit
  120. sav_stack:
  121.     mov    sp_sav,SP
  122.  
  123.      IF CCPM
  124.     ; search environment for comspec
  125.     ;
  126. srch_env:
  127.     push    CS            ; save ES
  128.     mov    ES,env_seg        ; point ES @ environment segment
  129.     xor    DI,DI            ; point DI to environment base
  130.     mov    SI,offset srch_str    ; point SI to search string
  131.     mov    CX,srch_len        ; length of search string
  132.     mov    AX,DI            ; clear AL for later null scan
  133.     mov    BX,SI            ; save pointer to search string
  134.     mov    DX,CX            ; save search length
  135. srch_lp:
  136.     cmp    bpt ES:[DI],0        ; environment end?
  137.     je    srch_x            ; if so, exit
  138.     mov    CX,DX            ; restore search length
  139.     mov    SI,BX            ; restore search pointer
  140.     repe    cmpsb            ; do block compare
  141.     je    mov_comspec        ; if ZF set, found it
  142.     not    CX            ; else, make CX a big number
  143.     repne    scasb            ;  and scan to end of string (null)
  144.     jmps    srch_lp            ; do it again
  145.  
  146. mov_comspec:
  147.     mov    BX,DI            ; save pointer to comspec
  148.     not    CX            ; change CX from 0 to FFFFh
  149.     repne    scasb            ;  and scan for end of string marker
  150.     not    CX            ; CX = length of comspec
  151.     mov    DI,offset program
  152.     mov    SI,BX            ; comspec now source
  153.     mov    DX,DS            ; exchange ES & DS
  154.     mov    AX,ES
  155.     mov    DS,AX
  156.     mov    ES,DX
  157.     rep    movsb            ; block copy compsec from environment
  158.     mov    DS,DX            ; restore DS
  159.  
  160. srch_x:
  161.     pop    ES            ; restore ES
  162.      ENDIF
  163.  
  164. load_exec:
  165.     cli
  166.     call    init_70            ; jiggle the controller
  167.     call    disable_70
  168.     call    init_70            ; turn on hi res timer
  169.  
  170.      IF CCPM
  171.     mov    AX,CS
  172.     mov    p1,AX
  173.     mov    p2,AX
  174.     mov    p3,AX
  175.     mov    DX,offset program
  176.     mov    BX,offset param_block
  177.     mov    sp_sav,SP
  178.     mov    AX,4B00h        ; load & execute function
  179.     sti
  180.     int    dos
  181.      ELSE
  182.     mov    SI,offset dta        ; point to command in default dta
  183.     sti                ; interrupts on
  184.     int    2Eh            ; back door into COMMAND.COM
  185.      ENDIF
  186.  
  187.     cli                ; interrupts off till stack back
  188.  
  189.     ; restore registers & stack
  190.     ;
  191.     mov    CX,CS
  192.     mov    SS,CX
  193.     mov    SP,CS:sp_sav
  194.     mov    DS,CX
  195.     mov    ES,CX
  196.  
  197.     call    disable_70        ; shut off hi res timer
  198.     sti                ; allow interrupts again
  199.  
  200.     mov    DX,offset msg
  201.     mov    AH,9
  202.     int    dos
  203.     mov    DI,offset buffer
  204.     mov    BX,time_lo
  205.     call    bin_2_dec
  206.  
  207. exit:
  208.     mov    AH,4Ch
  209.     int    dos
  210.  
  211. main    endp
  212.  
  213.     ; convert binary word to ascii decimal & write it in buffer
  214.     ; uses the 8086 divide instruction
  215.     ; parameters passed in registres as follows:
  216.     ;    AL    leading 0 fill character (usually 0 or space)
  217.     ;    BX    binary word to be converted
  218.     ;    CX    decimal digit limit (NTE 5)
  219.     ;    DX    (not preserved)
  220.     ;    SI    (not preserved)
  221.     ;    DI    address of buffer to put ascii decimals into
  222. bin_2_dec    proc near
  223.  
  224.     mov    CX,7
  225.     mov    AL,'0'
  226.     push    CX
  227.     rep    stosb            ; block fill, DI += CX
  228.     mov    bpt [DI],'$'
  229.     mov    bpt [DI-4],'.'
  230.     mov    bpt [DI-6],' '
  231.     mov    bpt [DI-7],' '
  232.     mov    AX,BX            ; put binary word into AX
  233.     mov    SI,10            ; put divisor in SI
  234.     pop    CX
  235.     inc    CX
  236.  
  237. next_digit:
  238.     dec    CX
  239.     jz    bin_2_dec_x
  240.     xor    DX,DX            ; clear dividend high word
  241.     div    SI            ; AX = (DX:AX)/SI, DX = remainder
  242.     add    DX,'0'            ; convert DL remainder byte to ascii
  243.     dec    DI            ; back step in buffer
  244.     mov    byte ptr [DI], DL    ; put character there
  245.     cmp    CX,5
  246.     jne    cont
  247.     dec    DI
  248. cont:
  249.     or    AX,AX            ; all done? (AX = 0?)
  250.     jnz    next_digit        ; if not, do another digit
  251. bin_2_dec_x:
  252.     mov    DX,offset buffer
  253.     mov    AH,9
  254.     int    dos
  255.     mov    DX,offset secs
  256.     mov    AH,9
  257.     int    dos
  258.     ret
  259. bin_2_dec    endp
  260.  
  261.  
  262.     ; initialize interrupt vector table
  263.     ;
  264. init_70        proc near
  265.     mov    AH,2
  266.     int    1Ah
  267.     mov    AH,3
  268.     int    1Ah
  269.     mov    AX,3570h        ; get interrupt 70h vectors
  270.     int    dos
  271.     mov    wpt i70jmp,BX        ; save them
  272.     mov    wpt i70jmp+2,ES
  273.     push    CS            ; restore ES
  274.     pop    ES
  275.     mov    dx,offset int_70
  276.     mov    ax,2570h        ; put new int_70 handler in table
  277.     cli
  278.     int    dos
  279.     call    enable_int        ; enable int_70
  280.     cli                ;   but shut it off for now
  281.     ret
  282. init_70        endp
  283.  
  284.     ; enable the high relolution timer
  285.     ;
  286. enable_int    proc    near
  287.     cli
  288.     mov    AL,0Bh
  289.     out    70h,AL
  290.     jmp    $+2
  291.     in    AL,71h
  292.     or    AL,01000000b        ; disable bit 6
  293.     mov    AH,AL
  294.     mov    AL,0Bh
  295.     out    70h,AL
  296.     jmp    $+2
  297.     mov    AL,AH
  298.     out    71h,AL
  299.     in    AL,0A1h
  300.     and    AL,11111110b        ; disable bit 0
  301.     out    0A1h,AL
  302.     mov    AL,20h
  303.     out    0A0h,AL
  304.     out    020h,AL
  305.     sti
  306.     ret
  307. enable_int    endp
  308.  
  309.     ; disable timer and repair interrupt vector table
  310.     ;
  311. disable_70    proc near
  312.     cli
  313.     push    DS
  314.     mov    DX,wpt i70jmp        ; get old int 70 vectors
  315.     mov    DS,wpt i70jmp+2
  316.     mov    ax,2570h        ; restore them
  317.     int    dos
  318.     pop    DS
  319.     mov    AL,0Bh
  320.     out    70h,AL
  321.     jmp    $+2
  322.     in    AL,71h
  323.     and    AL,10111111b        ; enable bit 6
  324.     mov    AH,AL
  325.     mov    AL,0Bh
  326.     out    70h,AL
  327.     jmp    $+2
  328.     mov    AL,AH
  329.     out    71h,AL
  330.     in    AL,0A1h
  331.     or    AL,00000001b        ; enable bit 0
  332.     out    0A1h,AL
  333.     mov    AL,20h
  334.     out    0A0h,AL
  335.     out    020h,AL
  336.     sti
  337.  
  338.     ; convert 1024 ticks/sec count to 1000 ticks/sec
  339.     ;
  340. dec_cnvt:
  341.     mov    CX,time_lo
  342. dec_lp:
  343.     sub    CX,1024
  344.     jbe    dec_lp_x
  345.     sub    time_lo,24
  346.     jmps    dec_lp
  347. dec_lp_x:
  348.     add    CX,1024
  349.     cmp    CX,768
  350.     jbe    b_768
  351.     sub    time_lo,6*3
  352.     jmps    disable_x
  353. b_768:
  354.     cmp    CX,512
  355.     jbe    b_512
  356.     sub    time_lo,6*2
  357.     jmps    disable_x
  358. b_512:
  359.     cmp    CX,256
  360.     jbe    disable_x
  361.     sub    time_lo,6
  362. disable_x:
  363.     ret
  364. disable_70    endp
  365.  
  366.     ; high resolution timer interrupt handler
  367.     ;
  368.     EVEN
  369. int_70        proc far
  370.     push    AX        ; save registers used
  371.     push    DS
  372.     mov    AX,CS
  373.     mov    DS,AX        ; point data segment to code segment
  374.     assume    DS:code
  375.     inc    time_lo        ; bump counters
  376.     adc    time_hi,0
  377.     pushf            ; prepare to 'call' original INT 70h
  378.     call    i70jmp        ; call & iret back here
  379.      IF NOT CLONE
  380.     call    enable_int    ; if bios shuts timer off, turn it back on
  381.      ENDIF
  382.     pop    DS        ; restore registers used
  383.     pop    AX
  384.     iret
  385. int_70        endp
  386.  
  387. last_byte    equ    $
  388. byt_cnt        equ    offset last_byte-tos
  389.  
  390. code    ends
  391.     end    at_timer
  392.