Board index » delphi » A potentially very serious bug in Pedt Scragg's CRT unit

A potentially very serious bug in Pedt Scragg's CRT unit

Hi all,

During the process of 386ifying the TP6 RTL, I haven't forgotten to
do something about Borlands wonderful CRT unit, which is not very
smartlink-friendly and which has a Delay function that no longer works
on fast CPUs, be it without causing an RTE 200.

Like Pedt's unit, my unit is smart-link friendly. It also detects if
an enhanced keyboard is present, but it assumes a modern PC and only
tests bit 4 of the keyboard status byte 1 at 0040h:0096h (see RBIL61,
MEMORY.LST) to detect such a keyboard.

However, to detect extended text modes, I've decided to use Pedt's
code and that's when I found something decidedly dodgy...

On his web-page he presents the following routine, provided by Osmo
Ronkanen, to detect if such a mode is in use:

Function Txtmode:boolean;
var b:byte;
   rg:registers;
   x,y:word;
begin
  x:=wherex;
  y:=wherey;
  gotoxy(1,1);
  txtmode:=false;
  b:=mem[$b800:0];
  rg.ah:=8;
  rg.bh:=0;
  intr($10,rg);
  if rg.al<>b then exit;

  {---}
  mem[$b800:0]:=b xor 255;
  rg.ah:=8;
  rg.bh:=0;
  intr($10,rg);
  Txtmode:=rg.al=b xor 255;
  {---}
  mem[$b800:0]:=b;
  gotoxy(x,y);
End;

and then writes us that the code was translated to assembler to ensure
a quick response speed. Using William Peavy's TWU1, the resulting TP6
code looks like this, after a little manual post-processing to add
more meaningful names...

09F0 A1 0000     mov   ax, Seg0040
09F3 57          push  di
09F4 06          push  es
09F5 8E C0       mov   es, ax
09F7 BF 0049     mov   di, CrtMode
09FA 26: 8A 05   mov   al, es:[di]
09FD 53          push  bx
09FE BF 004E     mov   di, CrtPageStart
0A01 26: 8B 1D   mov   bx, es:[di]
0A04 89 1E 0000  mov   CrtRegen, bx
0A08 BF 0062     mov   di, CrtPageNo
0A0B 26: 8A 1D   mov   bl, es:[di]
0A0E 88 1E 0000  mov   CrtPage, bl
0A12 5B          pop   bx
0A13 07          pop   es
0A14 5F          pop   di
0A15 3C 07       cmp   al, 7
0A17 75 03       jne   short 0A1Ch

0A19 E9 00A6     jmp   0AC2h

0A1C 3C 03       cmp   al, 3
0A1E 77 03       ja    short 0A23h

0A20 E9 009F     jmp   0AC2h

0A23 52          push  dx
0A24 51          push  cx

0A25 E8 0000     call  GetCursor
0A28 89 16 0000  mov   CrtXY, dx
0A2C 33 D2       xor   dx, dx
0A2E E8 0000     call  SetCursor
0A31 A1 0000     mov   ax, SegB800
0A34 06          push  es
0A35 57          push  di
0A36 8E C0       mov   es, ax
0A38 8B 3E 0000  mov   di, CrtRegen
0A3C 50          push  ax
0A3D 26: 8A 05   mov   al, es:[di]
0A40 A2 0000     mov   CrtB, al
0A43 58          pop   ax
0A44 5F          pop   di
0A45 07          pop   es
0A46 53          push  bx
0A47 B4 08       mov   ah, 8
0A49 8A 3E 0000  mov   bh, CrtPage
0A4D E8 0000     call  Video
0A50 5B          pop   bx
0A51 3A 06 0000  cmp   al, CrtB
0A55 75 63       jne   short 0ABAh

0A57 52          push  dx
0A58 8A 16 0000  mov   dl, CrtB
0A5C 80 F2 FF    xor   dl, FFh
0A5F A1 0000     mov   ax, SegB800
0A62 06          push  es
0A63 57          push  di
0A64 8E C0       mov   es, ax
0A66 8B 3E 0000  mov   di, CrtRegen
0A6A 26: 88 15   mov   es:[di], dl
0A6D 5F          pop   di
0A6E 07          pop   es
0A6F 53          push  bx
0A70 52          push  dx
0A71 B4 08       mov   ah, 8
0A73 8A 3E 0000  mov   bh, CrtPage
0A77 E8 0000     call  Video
0A7A 5A          pop   dx
0A7B 5B          pop   bx
0A7C 51          push  cx
0A7D 3A D0       cmp   dl, al
0A7F 75 03       jne   short 0A84h

0A81 B9 0001     mov   cx, 1
0A84 B9 0000     mov   cx, 0
0A87 A1 0000     mov   ax, SegB800
0A8A 06          push  es
0A8B 57          push  di
0A8C 8E C0       mov   es, ax
0A8E 8B 3E 0000  mov   di, CrtRegen
0A92 52          push  dx
0A93 8A 16 0000  mov   dl, CrtB
0A97 26: 88 15   mov   es:[di], dl
0A9A 5A          pop   dx
0A9B 5F          pop   di
0A9C 07          pop   es
0A9D 52          push  dx
0A9E 8B 16 0000  mov   dx, CrtXY
0AA2 E8 0000     call  SetCursor
0AA5 5A          pop   dx
0AA6 51          push  cx
0AA7 52          push  dx
0AA8 8B 16 0000  mov   dx, CrtXY
0AAC E8 0000     call  SetCursor
0AAF 5A          pop   dx
0AB0 59          pop   cx
0AB1 83 F9 00    cmp   cx, 0
0AB4 74 04       jz    short 0ABAh

0AB6 59          pop   cx
0AB7 5A          pop   dx
0AB8 EB 08       jmp   short 0AC2h

0ABA 59          pop   cx
0ABB 5A          pop   dx
0ABC B8 0003     mov   ax, 3
0ABF E8 0069     call  CrtInit

0AC2 E8 00B7     call  CrtSetup

The above code is a bit long, so remove all uninteresting instructions
and you're essentially left with this:

@9f0_1: mov   ax, Seg0040 ;       1
        jne   @a1c_2      ;      / \
        jmp   @ac2_6      ;     2   6
@a1c_2: cmp   al, 3       ;    / \
        ja    @a23_3      ;   3   6
        jmp   @ac2_6      ;   +
@a23_3: push  dx          ;   +
        push  cx          ;  / \
        jne   @aba_5      ; 5   +
;---
        push  dx          ; -   +
        push  cx          ; -  / \
        jne   @a84_4      ; 6  \0/
        mov   cx, 1       ;     4
@a84_4: mov   cx, 0       ;     |
        cmp   cx, 0       ;     5
        je    @aba_5      ;     -
        pop   cx          ;     -
        pop   dx          ;     6
        jmp   @ac2_6      ;
;---
@aba_5: pop   cx          ;
        pop   dx          ;
@ac2_6: call  CrtSetup    ;

Now take a close look at this code...

Just before @a84_4, cx is set to 1, but the next instruction
immediately sets it to 0 so the cmp cx, 0/je @aba_5 will always
jump to @aba_5, although it doesn't really seem to matter, because
_both_ paths leave two registers on the stack, as can be seen from
the small tree next to the code, where the numbers are the last digit
of the various labels...

Now, given that using this unit by substantial numbers of users has
not led to another VFAQ, I would almost conclude that both Osmo's
Pascal code and Pedt's asm code can dispense with the section between
the two {---} / ;--- comments...

Of course, should the jne @aba_5 test after the @a23_2 label ever not
jump, then the program will without a grain of doubt (I've tried it in
TD) crash, which may cause the "one potential bug" reported in January
2000.

I propose the following code, which I have tested for all possible
paths using TD, as a substantially shorter and bug-free replacement
for Pedt's original code, but would like to invite comments on it -
it uses 386 'sete' instructions, so would need minor changes for a
CRT unit that needs to be universally (aka on 86/286) usable.

CrtMode      EQU   (BYTE PTR 49H)
CrtPageStart EQU   (BYTE PTR 4EH)
CrtPageNo    EQU   (BYTE PTR 62H)

        push  es           ; save
        push  di           ;  all
        push  cx           ;   used
        push  dx           ;    registers

        mov   cx, Seg0040  ; need non-zero CL

        mov   es, cx
        mov   di, word ptr es:CrtPageStart
        mov   al, es:CrtPageNo
        mov   PageNo, al
        mov   al, es:CrtMode

        cmp   al, 7        ; mono
        je    @@4

        cmp   al, 3        ; 0..3 are text
        jbe   @@4

        mov   es, SegB800  ; Video

        call  GetCursor    ; WhereX + WhereY
        push  dx           ;---+ Save current (x, y) position
                           ;   |
        xor   dx, dx       ;   |
        call  SetCursor    ;   | GotoXY(1, 1)
                           ;   |
        push  bx           ;-+ |
        mov   ah, 8        ; | | Get char at (1, 1) via Int 10
        mov   bh, PageNo   ; | |
        call  Video        ; | |
        pop   bx           ;-+ |
                           ;   |
        mov   ah, es:[di]  ;   | Get char at (1, 1) directly
        cmp   ah, al       ;   |
        sete  cl           ;   | >>> 386 instruction!
        jne   @@1          ;   |
                           ;   |
        xor   al, -1       ;   |
        push  ax           ;--+|
        mov   es:[di], al  ;  || Set char at (1, 1) directly
                           ;  ||
        push  bx           ;-+||
        mov   ah, 8        ; ||| Get char at (1, 1) via Int 10
        mov   bh, PageNo   ; |||
        call  Video        ; |||
        pop   bx           ;-+||
                           ;  ||
        pop   dx           ;--+|
        mov   es:[di], dh  ;   | Restore char at (1, 1) directly
        cmp   al, dl       ;   |
        sete  cl           ;   | >>> 386 instruction!
                           ;   |
@@1:    pop   dx           ;---+
        call  SetCursor    ;     GotoXY(x, y)

@@4:    test  cl, cl       ;

        pop   dx           ; restore
        pop   cx           ;  all
        pop   di           ;   used
        pop   es           ;    registers

        jnz   @@3          ;

@@2:    mov   ax, 3        ; mode 3, 25x80
        call  CrtInit

@@3:    call  CrtSetup

Robert
--
Robert AH Prins
pr...@bigfoot.com

 

Re:A potentially very serious bug in Pedt Scragg's CRT unit


JRS:  In article <3da5b...@212.67.96.135>, seen in
news:comp.lang.pascal.borland, Robert AH Prins <pr...@onetel.net.uk>
posted at Thu, 10 Oct 2002 17:31:49 :-

Quote
> but it assumes a modern PC and only
>it uses 386 'sete' instructions, so would need minor changes for a
>CRT unit that needs to be universally (aka on 86/286) usable.

My PPC640 is still usable as a backup, so I would prefer a unit that is
compatible with any CPU that TP7/BP7 generate code for.

I use a 486/33 for much Pascal, but want my code to run on (a) my
PII/300, (b) anything else!

--
? John Stockton, Surrey, UK.  j...@merlyn.demon.co.uk   Turnpike v4.00   MIME. ?
  <URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
  <URL:http://www.merlyn.demon.co.uk/clpb-faq.txt> Pedt Scragg: c.l.p.b. mFAQ;
  <URL:ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip> Timo Salmi's Turbo Pascal FAQ.

Re:A potentially very serious bug in Pedt Scragg's CRT unit


Robert AH Prins <pr...@onetel.net.uk> said the following:

Quote

>However, to detect extended text modes, I've decided to use Pedt's
>code and that's when I found something decidedly dodgy...

Thanks for finding that Robert. Really much appreciated. Fixing ASAP -
probably not before the weekend as I've power supply problems here after
getting back (you may see some odd headers in newsgroup posts for the
next few days as I'm being completely rewired but now got someone to
recharge the elderly laptop for me).

Once fixed I'll copy to Garbo, Simtel and the Demon FTP server.

Thanks also for emailing me a copy of your post, appreciated. Long email
back to you as soon as I can.

Quote

[snip lots]

>Now, given that using this unit by substantial numbers of users has
>not led to another VFAQ, I would almost conclude that both Osmo's
>Pascal code and Pedt's asm code can dispense with the section between
>the two {---} / ;--- comments...

I would agree. I've had only a couple of comments - one posted here as
you indicate below and the other couple emailed to me. If other text
screens were being used extensively then I would have also expected it
to be a VFAQ - though hopefully it'd have been found and fixed quickly
if we'd had a number of comments here about it.

Quote

>Of course, should the jne @aba_5 test after the @a23_2 label ever not
>jump, then the program will without a grain of doubt (I've tried it in
>TD) crash, which may cause the "one potential bug" reported in January
>2000.

Agreed. Thanks again for finding the actual location. I've probably been
too close to it as I missed the above info every time I looked.

Quote
>it uses 386 'sete' instructions, so would need minor changes for a
>CRT unit that needs to be universally (aka on 86/286) usable.

I'll personally go for 8086 instructions so it'll be usable on anything
the resultant program runs on. I'd guess though that nearly everyone is
normally on a 386 or better these days so a 386 optimised version of any
of the Borland supplied units is going to be useful in most cases.

--
Pedt
Sex oriented junk mail on the increase?  Anagram of SMTP explains why!
Simple Mail Transfer Protocol = MAIL FROM: RCPT TO: - see all is {*word*40}

Other Threads