home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / lang / pascal / 8383 < prev    next >
Encoding:
Internet Message Format  |  1993-01-21  |  10.2 KB

  1. Path: sparky!uunet!munnari.oz.au!ariel.ucs.unimelb.EDU.AU!ucsvc.ucs.unimelb.edu.au!lugb!lux!cscmd
  2. Newsgroups: comp.lang.pascal
  3. Subject: Re: TP 6.0 Strange rounding problem (Debugger is *lying* to me!)
  4. Message-ID: <1993Jan19.084006.18267@lugb.latrobe.edu.au>
  5. From: cscmd@lux.latrobe.edu.au (Mitch Davis)
  6. Date: Tue, 19 Jan 1993 08:40:06 GMT
  7. Sender: news@lugb.latrobe.edu.au (USENET News System)
  8. References: <86277@ut-emx.uucp>
  9. Organization: La Trobe University
  10. Lines: 201
  11.  
  12. In article <86277@ut-emx.uucp> mmigdol@ccwf.cc.utexas.edu (michael a migdol) writes:
  13. >Here's a fragment of a program that was causing me some major grief last night.
  14. >
  15. >PROGRAM FOO;
  16.  
  17. I didn't look too closely at the problem, but here is a situation where
  18. the debugger IS lying, or something else is screwing up badly.  (Text of a 
  19. letter I sent Borland, and never got a reply from)
  20.  
  21. To:   Xxxxxx Xxxxx, Borland Pacific
  22. From: Mitch Davis (10/1072 Whitehorse Rd, Box Hill Vic. 3128 (03)-890-2062)
  23. Re:   Apparent problems with stack pushing and popping under TD 2.51
  24.  
  25. Here's a cut-down version of my program which displays the symptoms:
  26.  
  27.  1:{$M 2000,0,0}
  28.  2:program test_debugger_stack;
  29.  3:
  30.  4:uses dos;
  31.  5:
  32.  6:const ScanCode = 1900; {Scan code for alt-R}
  33.  7:
  34.  8:var OldInt16:procedure; {Put the old handler's address in here}
  35.  9:    active:boolean; {Shows our handler needs bypassing}
  36. 10:    regs:registers;
  37. 11:
  38. 12:procedure ShowHairs;
  39. 13:
  40. 14:begin
  41. 15:  {This is a do-nothing procedure which will have the body of the program}
  42. 16:end;
  43. 17:
  44. 18:procedure Int16Handler (flags,cs,ip,ax,bx,cx,dx,si,di,ds,es,bp:word); interrupt;
  45. 19:
  46. 20:{The above is straight out of the book.  I should be able to read and modify}
  47. 21:{any of these variables, and have them popped into the registers on IRET.   }
  48. 22:
  49. 23:begin
  50. 24:  {Support for extended kbds - The (ax and $EFFF) only lets AH=$00 or AH=$10}
  51. 25:  if (not active) and ((ax and $EFFF) = 0) then begin
  52. 26:    {To get here, we must be asking for a key, and not already involved.}
  53. 27:    active := true;
  54. 28:    regs.ax := ax;
  55. 29:    intr ($16,regs); {Let's get the key they asked us for}
  56. 30:    if regs.ax = ScanCode then ShowHairs; {Is it ours?}
  57. 31:    ax := regs.ax; {Put it in the stack space for the caller to use}
  58. 32:    active := false;
  59. 33:  end else asm
  60. 34:    {The first IF statement damaged some registers.  Refresh them}
  61. 35:    mov  ax, &ax; mov  dx, &dx
  62. 36:    {Perform a pseudo-interrupt to the old int16 handler}
  63. 37:    pushf
  64. 38:    call dword ptr [OldInt16]
  65. 39:    {some int16 routines modify the return flags, as well as many registers}
  66. 40:    {hence we want to subvert Turbo Pascal's stack cleanup by cleaning it  }
  67. 41:    {up ourselves.  We pop off as many registers as we can, effectively    }
  68. 42:    {throwing them away.  Why?  The Int16 routine we called may have       }
  69. 43:    {modified registers, and now we want our caller to see those changes.  }
  70. 44:    mov  ax, &ax ; {Put AX in it's proper place}
  71. 45:    pushf; pop  ax {Get the flags in AX}
  72. 46:    mov  ax, flags {And put them in their place too.  This is how the int  }
  73. 47:                   {16 handler changes the caller's flags.                 }
  74. 48:    pop  bp ; {We want to restore this}
  75. 49:    pop  ax ; {throw away caller's ES, we never changed it}
  76. 50:    pop  ds ; {we changed DS, so restore it}
  77. 51:    pop  ax ; {throw away caller's DI}
  78. 52:    pop  ax ; {throw away caller's SI}
  79. 53:    pop  ax ; {throw away caller's DX}
  80. 54:    pop  ax ; {throw away caller's CX}
  81. 55:    pop  ax ; {throw away caller's BX}
  82. 56:    pop  ax ; {Now AX has it's proper value, because we've popped where AX is}
  83. 57:    iret {Note this is procedure now has TWO IRETs - the TP supplied one,    }
  84. 58:  end;   {and the one we just did ourselves.                                 }
  85. 59:end;
  86. 60:
  87. 61:begin
  88. 62:  active := false;
  89. 63:  GetIntVec($16,@OldInt16);
  90. 64:  SetIntVec($16,@Int16Handler);
  91. 65:  readln; {This is to do an in-program test of the int16 handler}
  92. 66:  SetIntVec($16,@OldInt16);
  93. 67:end.
  94.  
  95. What's happened up to this point:
  96.  o I compiled the program.
  97.  o I typed "td test".
  98.  o I set a breakpoint on the "begin" of "Int16Handler".
  99.  o I opened the Code window, and closed the Source and Watch windows.
  100.  o I pressed Ctrl-F2, then F9.  Execution stops where you see below.  Good.
  101.    [Note I have replaced control characters with Xs, otherwise my faxcard]
  102.    [wouldn't like me!  Note that every time you press Ctrl-F2 F9, the    ]
  103.    [outcome is different (see below).  The only thing that's predictable ]
  104.    [is that it's not what is wanted!                                     ]
  105. +-[.]-CPU 80286-----------------------------------------------+------3---[X]-+
  106. |TEST_DEBUGGER_STACK.INT16HANDLER: begin                      x ax 0100  |c=0|
  107. |  cs:000C>50             push   ax                           . bx 0324  |z=1|
  108. |  cs:000D 53             push   bx                           % cx 0001  |s=0|
  109. |  cs:000E 51             push   cx                           % dx 0000  |o=0|
  110. |  cs:000F 52             push   dx                           % si 0041  |p=1|
  111. |  cs:0010 56             push   si                           % di 035E  |a=0|
  112. |  cs:0011 57             push   di                           % bp 07C4  |i=0|
  113. |  cs:0012 1E             push   ds                           % sp 083A  |d=0|
  114. |  cs:0013 06             push   es                           % ds 0070  |   |
  115. |  cs:0014 55             push   bp                           % es 0279  |   |
  116. |  cs:0015 89E5           mov    bp,sp                        % ss 0279  |   |
  117. |  cs:0017 B8125F         mov    ax,5F12                      % cs 5E96  |   |
  118. |  cs:001A 8ED8           mov    ds,ax                        % ip 000C  |   |
  119. |TEST_DEBUGGER_STACK.25:  if (not active) and ((ax and $EFFF) %----------+---+
  120. |  cs:001C 803E480000     cmp    byte ptr [0048],00           x ss:0846 0E10 |
  121. +x.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%x+ ss:0844 0201 |
  122. |  es:0838 2B 13 96 02 3A 0F 70 00 xxxxxxxx                   | ss:0842 0E87 |
  123. |  es:0840 46 02 87 0E 01 02 10 0E xxxxxxxx                   | ss:0840 0246 |
  124. |  es:0848 94 0D 9D 0C 06 03 79 02 xxxxxxxx                   | ss:083E 0070 |
  125. |  es:0850 70 00 80 74 00 00 69 5F xxxxxxxx                   | ss:083C 0F3A |
  126. |  es:0858 90 10 69 5F 00 00 42 5D xxxxxxxx                   | ss:083A>0296 |
  127. +-------------------------------------------------------------+--------------+
  128. At this point, pressing F7 should push AX onto the stack.  That is, the IP
  129. arrow should move to CS:000D, the stack arrow move to SS:0838, and SS:0838
  130. becomes 0100, which is the value in AX.  I press F7:
  131.  
  132. [comp.lang.pascal note, I'm deleting further line and box chars]
  133.  
  134.   [ ] CPU 80286
  135. |TEST_DEBUGGER_STACK.INT16HANDLER: begin              ax 0100  c=0|
  136. |  cs:000C 50          push     ax                  bx 0324  z=1|
  137. |  cs:000D>53          push     bx                  cx 0001  s=0|
  138. |  cs:000E 51          push     cx                  dx 0000  o=0|
  139. |  cs:000F 52          push     dx                  si 0041  p=1|
  140. |  cs:0010 56          push     si                  di 035E  a=0|
  141. |  cs:0011 57          push     di                  bp 07C4  i=0|
  142. |  cs:0012 1E          push     ds                  sp 0838  d=0|
  143. |  cs:0013 06          push     es                  ds 0070      |
  144. |  cs:0014 55          push     bp                  es 0279      |
  145. |  cs:0015 89E5       mov     bp,sp                  ss 0279      |
  146. |  cs:0017 B8125F      mov     ax,5F12              cs 5E96      |
  147. |  cs:001A 8ED8       mov     ds,ax                  ip 000D      |
  148. |TEST_DEBUGGER_STACK.25:  if (not active) and ((ax and $EFFF)
  149. |  cs:001C 803E480000     cmp    byte ptr [0048],00           ss:0844 0201
  150.                                   ss:0842 0E87
  151. |  es:0838 2B 13 96 02 3A 0F 70 00 xxxxxxxx              ss:0840 0246
  152. |  es:0840 46 02 87 0E 01 02 10 0E xxxxxxxx                   ss:083E 0070
  153. |  es:0848 94 0D 9D 0C 06 03 79 02 xxxxxxxx                   ss:083C 0F3A
  154. |  es:0850 70 00 80 74 00 00 5A 76 xxxxxxxx                   ss:083A 0296
  155. |  es:0858 90 10 5A 76 00 00 42 5D xxxxxxxx                   ss:0838>132B
  156.  
  157. The IP arrow has moved, and so has the Stack arrow.  But see that the value
  158. pushed onto the stack was not 0100, but 132B, which was the value already
  159. present in the stack (see picture 1 in the data pane).  I press Ctrl-F2 and
  160. then F9, then F7, F7:
  161.  
  162.  
  163.  TEST_DEBUGGER_STACK.INT16HANDLER: begin              ax 0100  c=0
  164.    cs:000C 50          push     ax                  bx 0324  z=1
  165.    cs:000D 53          push     bx                  cx 0001  s=0
  166.    cs:000E>51          push     cx                  dx 0000  o=0
  167.    cs:000F 52          push     dx                  si 0041  p=1
  168.    cs:0010 56          push     si                  di 035E  a=0
  169.    cs:0011 57          push     di                  bp 07C4  i=0
  170.    cs:0012 1E          push     ds                  sp 0836  d=0
  171.    cs:0013 06          push     es                  ds 0070
  172.    cs:0014 55          push     bp                  es 0279
  173.    cs:0015 89E5       mov     bp,sp                  ss 0279
  174.    cs:0017 B8125F      mov     ax,5F12              cs 5E96
  175.    cs:001A 8ED8       mov     ds,ax                  ip 000E
  176.  TEST_DEBUGGER_STACK.25:  if (not active) and ((ax and $EFFF)
  177.    cs:001C 803E480000      cmp     byte ptr [0048],00          ss:0842 0E87
  178.                                   ss:0840 0246
  179.    es:0838 00 01 96 02 3A 0F 70 00 xxxxxxxx              ss:083E 0070
  180.    es:0840 46 02 87 0E 01 02 10 0E xxxxxxxx              ss:083C 0F3A
  181.    es:0848 94 0D 9D 0C 06 03 79 02 xxxxxxxx              ss:083A 0296
  182.    es:0850 70 00 80 74 00 00 69 5F xxxxxxxx              ss:0838 0100
  183.    es:0858 D2 10 69 5F 00 00 42 5D xxxxxxxx              ss:0836>0324
  184.  
  185.  
  186.   This time, AX gets correctly pushed, and it CLAIMS that BX gets correctly
  187. pushed, but looking at the stack area in the data pane shows that Turbo
  188. Debugger is not being entirely accurate - SS:0836 in the stack pane is
  189. 0324, whereas SS:0836 (SS=ES) in the data pane shows 0296.  If I believed
  190. the stack pane (as I used to), then whenever I tried to access the BX
  191. variable later in the handler, I would get the value 0296.  This is how I
  192. first suspected that the debugger had a problem.
  193.  
  194. So you see, I'm at a bit of a loose end.  I realised there was a problem, and
  195. I've investigated it to try and find out what was happening.  I've since had
  196. a look in the debugger manual, and I can't see any place where it expressly
  197. states that TD is not for debugging interrupts; in fact the section on
  198. debugging TSRs and going Resident explicitly states that that is what you
  199. will be doing.    If this is the case, I think maybe TD has some limitations
  200. when debugging TSRs.
  201.  
  202. I hope this information is of benefit to you in improving what is _the_
  203. definitive software-based debugger!
  204.  
  205. Yours,
  206.  
  207. Mitch Davis.
  208. ----------------------------------------------------------
  209. Anyone else care to comment?  Note that all that hairy Pascal stuff
  210. never gets executed - you put a breakpoint in before that point.
  211.  
  212. Mitch.
  213.