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