home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 355_01 / slk1.exe / SHERLOCK / PRF.ASM < prev    next >
Assembly Source File  |  1988-07-22  |  11KB  |  459 lines

  1. ;    Profiler for Sherlock--low level routines
  2. ;
  3. ;    WARNING! use this file at your own risk.  See further warnings below.
  4. ;
  5. ;    source:  prf.asm
  6. ;    started: November 10, 1986
  7. ;    version: July 22, 1988
  8. ;
  9. ;
  10. ;    Copyright (C) 1987, 1988 by Edward K. Ream.
  11. ;    All Rights reserved.
  12. ;
  13. ;
  14. ;    This file contains an interrupt handler for timing interrupts,
  15. ;    and routines to install and de-install the handler.
  16. ;
  17. ;    NOTE:    This file is required only if the TIME_STATS variable is
  18. ;        #define'd in the file SHERLOCK.C.
  19. ;
  20. ;    NOTE:    Assemble this file with the Microsoft MASM assembler and
  21. ;        link this file with the Microsoft or TURBO C linkers.
  22. ;        Use the /MX and /ML options when assembling this file.
  23. ;
  24. ;    NOTE:   Use the /DNEAR option on the MASM command line when producing
  25. ;        a .obj file to be used with memory models with small code 
  26. ;        space, namely the Microsoft small and compact models.  Do NOT
  27. ;        use the /DNEAR option when using the other memory models.
  28. ;
  29. ;    WARNING!  You must MAKE SURE that you change this code correctly
  30. ;          reflects the memory model you are using in your C code.
  31. ;          If you get this wrong, the code will die a quick death.
  32. ;
  33. ;    WARNING!  USE THIS CODE AT YOUR OWN RISK.  This code may cause
  34. ;          your system to hang.  This code contains potential machine 
  35. ;          dependencies.  See further warnings below.  However, this
  36. ;          code has been tested on both PC clones and AT clones.
  37. ;
  38. ;    WARNING!  The code changes interrupts 33-36 in an attempt to trap
  39. ;          ALL exit points from the program.  If this attempt is not
  40. ;          successful, the system will hang and a reboot is the only
  41. ;          way out.  DO NOT, repeat DO NOT, use this code if that
  42. ;          possibility is unacceptable!!!
  43. ;
  44. ;    WARNING!  The code messes with the timing rate of the system clock to
  45. ;          increase the number of timing interrupts without changing 
  46. ;          number of 'tick' interrupts visible to the rest of the 
  47. ;          system. To do this, it must touch the underlying clock 
  48. ;          hardware.  In particular this code fiddles with the 8251
  49. ;          timer chip. THIS CODE MAY NOT WORK if that chip does not
  50. ;          exist on your machine.
  51. ;
  52.  
  53.         TITLE    prf.asm
  54.  
  55. DGROUP        GROUP _DATA
  56.         ASSUME ds:DGROUP
  57.  
  58. ;
  59. ;    Declare variables which are defined in sherlock.c
  60. ;    (sl_count and sl_speed).
  61. ;    Also define local variables.
  62. ;
  63.  
  64. _DATA        SEGMENT WORD PUBLIC 'DATA'
  65.  
  66.         EXTRN    _sl_count:DWORD
  67.         EXTRN    _sl_speed:WORD
  68.  
  69. timer_count    dw    1        ;internal timer count
  70. timer_speed    dw    1        ;internal timer speed
  71. installed    db    0        ;true = routines installed
  72.  
  73. _DATA        ENDS
  74.  
  75. _TEXT        SEGMENT    BYTE PUBLIC 'CODE'
  76.         ASSUME cs:_TEXT
  77.  
  78. ;
  79. ;    Storage area for saved interrupt vectors.
  80. ;
  81. ;    The interrupt installation routine, sl_von, saves the old value of
  82. ;    the interrupt vectors here.  The de-initialization routine, sl_voff,
  83. ;    restores the vectors using these values.
  84. ;
  85. ;    WARNING!  We must attempt to trap ALL exits from the program, because
  86. ;          we can not rely on the program itself to call sl_voff.
  87. ;          After all, we ARE debugging, so aborting the program must be
  88. ;          expected.  THIS CREATES A PROBLEM, because if the program
  89. ;          ever terminates without sl_von being called, the interrupt
  90. ;          handlers will not be restored and the system will hang.
  91. ;
  92. ;    These vectors MUST be in the code segment;  Indeed, when we do the
  93. ;    jump-indirect that gets us to the machine's routines, we must have
  94. ;    all the processor registers and flags restored to their original
  95. ;    values.  If we change ds, (in order to pick these out of the data
  96. ;    segment and do the indirect jump), there's no way to change ds back
  97. ;    again to whatever the caller had it.
  98. ;
  99. ;    The fact that these vectors are in the code segment instead of the
  100. ;    data segment makes the code below much more tricky than usual.
  101. ;    Be warned.  Do not change the code in sl_von and sl_voff without
  102. ;    careful thought.
  103. ;
  104.  
  105. old_8        label    DWORD    ;Tick interrupt vector
  106. ofs8        dw    0    ;offset
  107. seg8        dw    0    ;segment
  108.  
  109. old_33        label    DWORD    ;Invoke "DOS 21 hex" interrupt vector
  110. ofs33        dw    0    ;offset
  111. seg33        dw    0    ;segment
  112.  
  113. old_34        label    DWORD    ;Terminate Address
  114. ofs34        dw    0    ;offset
  115. seg34        dw    0    ;segment
  116.  
  117. old_35        label    DWORD    ;Break Address
  118. ofs35        dw    0    ;offset
  119. seg35        dw    0    ;segment
  120.  
  121. old_36        label    DWORD    ;Critical Error Handler address
  122. ofs36        dw    0    ;offset
  123. seg36        dw    0    ;segment
  124.  
  125. ;
  126. ;    Install the interrupt handler for the timer (tick) interrupt.
  127. ;
  128. ;    It contains a safeguard against overwriting the old_xx vectors
  129. ;    so as to minimize the chances of getting the new values of
  130. ;    the vectors saved, and thereby having this code locked into
  131. ;    place forever.
  132. ;
  133.  
  134.         PUBLIC _sl_von
  135.  
  136. IFDEF NEAR
  137. _sl_von        proc    near        ;for small memory models
  138. ELSE
  139. _sl_von        proc    far        ;for large memory models
  140. ENDIF
  141.  
  142.         push    es
  143.         push    ds
  144.         mov    ax,DGROUP    ;actually, needed only for multisegment
  145.         mov    ds,ax        ;programs
  146.         cli            ;disable maskable intertupts
  147. ;
  148. ;    WARNING!  The set_timer routine contains machine dependent code.
  149. ;          It MAY NOT WORK on your machine.
  150. ;
  151.  
  152.         call set_timer        
  153.  
  154. ;
  155. ;    Do not replace vectors if they are already replaced.
  156. ;
  157.         test    installed,0ffh    ;vectors already installed?
  158.         jz    noskip
  159.         jmp    skipvec
  160. noskip:
  161.         mov    installed,0ffh
  162. ;
  163. ;    Replace existing 'tick' interrupt (interrupt 8).
  164. ;
  165.         mov    ax,cs
  166.         mov    ds,ax
  167. ;
  168. ;    Caution: these settings use ds=cs, not ds of this module's data!!!
  169. ;
  170.         mov    ah,35h        ;get interrupt vector
  171.         mov    al,8        ;8
  172.         int    21h        ;into ES:BX
  173.  
  174.         mov    seg8,es
  175.         mov    ofs8,bx
  176.         mov    dx,offset svc_timer
  177.  
  178.         mov    ah,25h        ;set interrupt vector
  179.         mov    al,8        ;8
  180.         int    21h        ;from DS:DX
  181.         
  182. ;
  183. ;    Replace existing interrupt 33 (21 hex).
  184. ;
  185.         mov    ah,35h        ;get interrupt vector
  186.         mov    al,33        ;33
  187.         int    21h        ;into ES:BX
  188.  
  189.         mov    seg33,es
  190.         mov    ofs33,bx
  191.         mov    dx,offset do33
  192.         
  193.         mov    ah,25h        ;set interrupt vector
  194.         mov    al,33        ;33
  195.         int    21h
  196. ;
  197. ;    Replace existing interrupt 34 (decimal).
  198. ;
  199.         mov    ah,35h        ;get interrupt vector
  200.         mov    al,34        ;34
  201.         int    21h        ;into ES:BX
  202.  
  203.         mov    seg34,es
  204.         mov    ofs34,bx
  205.         mov    dx,offset rest34
  206.         
  207.         mov    ah,25h        ;set interrupt vector
  208.         mov    al,34        ;34
  209.         int    21h
  210. ;
  211. ;    Replace existing interrupt 35.
  212. ;
  213.         mov    ah,35h        ;get interrupt vector
  214.         mov    al,35        ;35
  215.         int    21h        ;into ES:BX
  216.  
  217.         mov    seg35,es        ;:cs
  218.         mov    ofs35,bx
  219.         mov    dx,offset rest35
  220.         
  221.         mov    ah,25h        ;set interrupt vector
  222.         mov    al,35        ;35
  223.         int    21h
  224. ;
  225. ;    Replace existing interrupt 36.
  226. ;
  227.         mov    ah,35h        ;get interrupt vector
  228.         mov    al,36        ;36
  229.         int    21h        ;into ES:BX
  230.  
  231.         mov    seg36,es        ;:cs
  232.         mov    ofs36,bx
  233.         mov    dx,offset rest36
  234.         
  235.         mov    ah,25h        ;set interrupt vector
  236.         mov    al,36        ;36
  237.         int    21h
  238. ;
  239. ;    Caution: ds is still cs here!
  240. ;
  241. skipvec:
  242.         sti            ;enable maskable interrupts
  243.         pop    ds
  244.         pop    es
  245.         ret
  246.  
  247. _sl_von        ENDP
  248.  
  249. ;
  250. ;    This routine is entered when the program terminates, and is normally
  251. ;    entered by way of one of the altered interrupts 33-36.
  252. ;
  253. ;    It is permissible to call it more than once, since the saved vectors
  254. ;    are not overwritten by anything.  
  255. ;
  256.  
  257.         PUBLIC _sl_voff
  258.  
  259. IFDEF NEAR
  260. _sl_voff    PROC near        ;for small memory models
  261. ELSE
  262. _sl_voff    PROC far        ;for large memory models
  263. ENDIF
  264.  
  265.         push    ds
  266.         push    dx
  267.         push    ax
  268.         mov    ax,DGROUP
  269.         mov    ds,ax
  270.         cli            ;disable maskable interrupts
  271. ;
  272. ;    Restore timer 0 to power-up value.
  273. ;    WARNING!  This code MAY NOT WORK on your machine.
  274. ;
  275.         mov    al,36h
  276.         out    43h,al
  277.         mov    al,0
  278.         out    40h,al
  279.         out    40h,al
  280. ;
  281. ;    Cancel installation flag.
  282. ;
  283.         mov    installed,0
  284. ;
  285. ;    Caution: ds is obviously no good from here on down!
  286. ;
  287. ;    Restore 'tick' interrupt (interrupt 8).
  288. ;
  289.         lds    dx,old_8
  290.         mov    ah,25h        ;set interrupt vector
  291.         mov    al,8        ;
  292.         int    21h
  293. ;
  294. ;    Restore interrupt 33.
  295. ;
  296.         lds    dx,old_33
  297.         mov    ah,25h        ;set interrupt vector
  298.         mov    al,33        ;33
  299.         int    21h
  300. ;
  301. ;    Restore interrupt 34.
  302. ;
  303.         lds    dx,old_34    ;cs:old_34, of course
  304.         mov    ah,25h        ;set interrupt vector
  305.         mov    al,34        ;34
  306.         int    21h
  307. ;
  308. ;    Restore interrupt 35.
  309. ;
  310.         lds    dx,old_35
  311.         mov    ah,25h        ;set interrupt vector
  312.         mov    al,35        ;35
  313.         int    21h
  314. ;
  315. ;    Restore interrupt 36.
  316. ;
  317.         lds    dx,old_36
  318.         mov    ah,25h        ;set interrupt vector
  319.         mov    al,36        ;36
  320.         int    21h
  321. ;
  322. ;    Caution: ds is not valid here.
  323. ;
  324.         pop    ax
  325.         pop    dx
  326.         pop    ds
  327.         sti
  328.         ret
  329. ;
  330. ;    The following routines replace the original interrupt vectors 33-36.
  331. ;    They simply de-install the timer interrupt (svc_timer) and then chain
  332. ;    to the original interrupt vector.
  333. ;
  334. ;    The do33 (dos 21 hex) interrupt is slightly more complicated.
  335. ;    This is the DOS Functions software interrupt.  All DOS functions except
  336. ;    function 0 (terminate) and 4c hex (terminate process) are passed 
  337. ;    through unchanged.  Functions 0 and 4c cause the timer interrupt to
  338. ;    be de-installed.
  339. ;
  340. do33:
  341.         cmp    ah,4ch    ;terminate process?
  342.         je    rest33
  343.         cmp    ah,0    ;terminate?
  344.         je    rest33
  345.         jmp    old_33    ;just pass through the request unchanged.
  346.  
  347. rest33:
  348.         call    _sl_voff
  349.         jmp    old_33
  350. rest34:
  351.         call    _sl_voff
  352.         jmp    old_34
  353. rest35:
  354.         call    _sl_voff
  355.         jmp    old_35
  356. rest36:
  357.         call    _sl_voff
  358.         jmp    old_36
  359.  
  360. _sl_voff    ENDP
  361.  
  362. ;
  363. ;    Service a timer interrupt.
  364. ;
  365. ;    This code bumps the (long) sl_count counter defined in sherlock.c.
  366. ;    Then, depending on the 'speed up factor', it either chains to the
  367. ;    original 'tick' interrupt routine or returns from the interrupt
  368. ;    immediately.
  369. ;
  370. svc_timer    PROC near
  371.  
  372.         push    ds
  373.         push    ax
  374. ;
  375. ;    The next statement has to use DGROUP, not _DATA, as the segment base.
  376. ;    Ours is not to reason why...
  377. ;
  378. ;    NOTE: even in a small-model program, the ds is apt not to be set
  379. ;    correctly at the entry to svc_timer, since the int could occur
  380. ;    from inside a utility or DOS function not part of the C program.
  381. ;    In Microsoft C, the ds setting at the outset (__astart) isn't the
  382. ;    same as the setting at _main, even for the small model!
  383. ;
  384.         mov    ax,DGROUP
  385.         mov    ds,ax
  386.  
  387.         inc    WORD PTR _sl_count 
  388.         jnz    svc_1
  389.         inc    WORD PTR _sl_count+2
  390. svc_1:
  391. ;
  392. ;    See if we should chain to the original tick interrupt or
  393. ;    return from the interrupt right away.  This depends on the speed-up
  394. ;    factor, i.e., the settings of sl_speed and timer_count.
  395. ;
  396.         dec    timer_count
  397.         jnz    skip
  398.         mov    ax,timer_speed
  399.         mov    timer_count,ax
  400.         cmp    ax,_sl_speed
  401.         jz    svc_2
  402.         call    set_timer
  403. ;
  404. ;    Chain to the original interrupt.
  405. ;
  406. svc_2:
  407.         pop    ax
  408.         pop    ds
  409.         jmp    old_8
  410. ;
  411. ;    Return from the interrupt without chaining to the original interrupt.
  412. ;
  413. skip:
  414.         mov    al,20h    
  415.         out    20h,al        ;send EOI to 8259
  416.         pop    ax
  417.         pop    ds
  418.         iret            ;return from interrupt
  419.  
  420. svc_timer    ENDP
  421.  
  422. ;
  423. ;    Set up timer according to speed ratio.
  424. ;    This needs to push all registers it uses, except ax.
  425. ;
  426. ;    WARNING!  This is MACHINE DEPENDENT CODE.  There is NO guarantee
  427. ;          that this code will work on your machine.
  428. ;          If it does not work, you may just comment it all out, but
  429. ;          then you will be stuck with the 18 hz. default clock rate.
  430. ;
  431. set_timer    PROC    NEAR
  432.         push    dx
  433.         mov    ax,_sl_speed
  434.         cmp    ax,0
  435.         jnz    set_1
  436.         mov    ax,1
  437. set_1:
  438.         mov    timer_speed,ax
  439.         mov    timer_count,ax
  440.  
  441.         mov    ax,0ffffh
  442.         mov    dx,0
  443.         div    timer_speed    ;sl_speed is a word, so it's 32:16
  444.         mov    dx,ax        ;dx = setting to be put into timer
  445.  
  446.         mov    al,36h        ;timer 0, mode 3
  447.         out    43h,al
  448.         mov    al,dl        ;lsb
  449.         out    40h,al
  450.         mov    al,dh        ;msb
  451.         out    40h,al
  452.         pop    dx
  453.         ret
  454. set_timer    ENDP
  455.  
  456. _TEXT        ENDS
  457.  
  458.         END
  459.