www.digitalmars.com         C & C++   DMDScript  

c++.dos.16-bits - Bug...? register variable CX is used for shifting another register variable SI.

reply "Kiyuki" <sakura tennodai.com> writes:
Hello,

I'm encountered sc's bug which uses register CX as a register variable, but
CL is used for
another register. These are fragments of C++ code and obj2asm's output.

The variable lo is assigned to register CX, but CL is used to shift SI with
8bit.
So CX's value is rotten.

Thanks.

// bug.cpp

class text12 {
public:
  char far* _f3;
  char far* _image;
  char buf[18];
  int zenkanji2(unsigned code);
};

int text12::zenkanji2(unsigned code) {
  int k;
  if (! _f3) return 0;

  unsigned hi;
  if (0x989f <= code && code <= 0x9ffe) {
    hi = ((code / 0x100) - 0x98) & 0xff;
  } else if (0xe040 <= code && code <= 0xeaa4) {
    hi = ((code / 0x100) - (0x98 + 0x40)) & 0xff;
  } else {
    return 0;
  }

  unsigned lo = code & 0x00ff;

  if (0x40 <= lo && lo < 0x7f) {
    lo -= 0x40;
  } else if (0x7f < lo && lo <= 0xfc) {
    lo -= 0x41;
  } else {
    return 0;
  }

  unsigned offset = (hi*188 + lo - 94);
  offset *= 18;

  for (k = 0; k < 18; k++) {
    _image[k] = _f3[offset + k];
  }

  return 1;
}

// ---------------------

c:\> sc -c -msw -NL -j0 -a1 -0 -o+space -Bj -Ab -Aa -gl -e  -s bug.cpp
c:\> obj2asm bug


_TEXT segment word use16 public 'CODE' ;size is 201
_TEXT ends
_DATA segment word use16 public 'DATA' ;size is 0
_DATA ends
CONST segment word use16 public 'CONST' ;size is 0
CONST ends
_BSS segment word use16 public 'BSS' ;size is 0
_BSS ends
DGROUP group _DATA,CONST,_BSS
 extrn __chkstk

 public ?zenkanji2 text12  QACHI Z
_TEXT segment
 assume CS:_TEXT
;
;class text12 {
;public:
;  char far* _f3;
;  char far* _image;
;  char buf[18];
;  int zenkanji2(unsigned code);
;};
;
;int text12::zenkanji2(unsigned code) {
?zenkanji2 text12  QACHI Z:
  push BP
  mov BP,SP
  mov AX,2
  call near ptr __chkstk
  push SI
  push DI
  mov CX,6[BP]
  mov DX,4[BP]
;  int k;
;  if (! _f3) return 0;
  mov BX,DX
  mov AX,2[BX]
  or AX,[BX]
  je L75
;
;  unsigned hi;
;  if (0x989f <= code && code <= 0x9ffe) {
  cmp CX,0989Fh
  jb L37
  cmp CX,09FFEh
  ja L37
;    hi = ((code / 0x100) - 0x98) & 0xff;
  mov SI,CX
  mov CX,8              ;;;;;;;;;;;;; HERE HERE ;;;;;;;;;;;;
  shr SI,CL
  add SI,0FF68h
  and SI,0FFh
  jmp short L52
;  } else if (0xe040 <= code && code <= 0xeaa4) {
L37:  cmp CX,0E040h
  jb L75
  cmp CX,0EAA4h
  ja L75
;    hi = ((code / 0x100) - (0x98 + 0x40)) & 0xff;
  mov SI,CX
  mov CX,8              ;;;;;;;;;;;;; HERE HERE ;;;;;;;;;;;;
  shr SI,CL
  add SI,0FF28h
  and SI,0FFh
;  } else {
;    return 0;
;  }
;
;  unsigned lo = code & 0x00ff;
;
;  if (0x40 <= lo && lo < 0x7f) {
L52:  mov BX,CX         ;;;;;;;;;;;;; HERE HERE ;;;;;;;;;;;;
  xor BH,BH
  cmp BX,040h
  jb L65
  cmp BX,07Fh
  jae L65
;    lo -= 0x40;
  add BX,0FFFFFFC0h
  jmp short L7F
;  } else if (0x7f < lo && lo <= 0xfc) {
L65:  cmp BX,07Fh
  jbe L75
  cmp BX,0FCh
  ja L75
;    lo -= 0x41;
  add BX,0FFFFFFBFh
  jmp short L7F
L75:  xor AX,AX
  pop DI
  pop SI
  mov SP,BP
  pop BP
  ret 4
L7F:  mov 4[BP],DX
;  } else {
;    return 0;
;  }
;
;  unsigned offset = (hi*188 + lo - 94);
  mov AX,SI
  mov CL,0BCh
  mul CX
  mov DI,AX
  add DI,BX
  add DI,0FFFFFFA2h
;  offset *= 18;
  mov AX,012h
  mul DI
  mov DI,AX
;
;  for (k = 0; k < 18; k++) {
  mov word ptr -2[BP],0
  mov DX,4[BP]
  mov CX,-2[BP]
  jmp short LB9
;    _image[k] = _f3[offset + k];
LA3:  mov AX,DI
  add AX,CX
  mov BX,DX
  les SI,[BX]
  add SI,AX
  mov AL,ES:[SI]
  les BX,4[BX]
  add BX,CX
  mov ES:[BX],AL
;  }
  inc CX
LB9:  cmp CX,012h
  jb LA3
;
;  return 1;
  mov AX,1
;}
  pop DI
  pop SI
  mov SP,BP
  pop BP
  ret 4
_TEXT ends
_DATA segment
_DATA ends
CONST segment
CONST ends
_BSS segment
_BSS ends
 end

Compilation finished at Tue Jul 17 00:35:12
Jul 16 2001
parent reply Heinz Saathoff <hsaat bre.ipnet.de> writes:
Kiyuki schrieb...
 Hello,
 
 I'm encountered sc's bug which uses register CX as a register variable, but
 CL is used for
 another register. These are fragments of C++ code and obj2asm's output.
 
 The variable lo is assigned to register CX, but CL is used to shift SI with
 8bit.
 So CX's value is rotten.

Even if I haven't fully analyzed the code it seems to be ok because the compiler moves the old value of CX to SI _before_ it assigns a shift count to CX.
[snip]
  ja L37
 ;    hi = ((code / 0x100) - 0x98) & 0xff;
   mov SI,CX

here CX is move to SI
   mov CX,8              ;;;;;;;;;;;;; HERE HERE ;;;;;;;;;;;;
   shr SI,CL
   add SI,0FF68h
   and SI,0FFh
   jmp short L52

Shift's and masks are done with SI I've noticed that SC often rearanges register values. But this is absolute legal and no error! Regards, Heinz
Jul 16 2001
parent reply "Kiyuki" <sakura tennodai.com> writes:
In sample source, variables are assigned 
  code -> CX,
  hi   -> SI,
  lo   -> BX.

Code fragment of this sample:

hi = ((code/0x100) - 0x98) & 0xff; (1)
lo = code & 0xff;                  (2)
if (0x40 <= lo && lo < 0x7f) { ... (3)

Statement (1) is compiled to

  mov SI,CX
  mov CX,8
  shr SI,CL
  add SI,0xff68h
  and SI,0ffh

It seems good, indeed. But register CX is changed to 8; so 
the value of the variable code is 8 which I don't expected.

Statements (2), (3) are compiled to

  mov BX,CX
  xor BH,BH
  cmp BX,040h
  jb L65
  cmp BX,07fh
  jae L65 ...

When this code runs, the variable lo is always 8, because 
the register variable CX is assigned to 8.

 Even if I haven't fully analyzed the code it seems to be ok because the 
 compiler moves the old value of CX to SI _before_ it assigns a shift 
 count to CX.

Thanks,
Jul 16 2001
parent reply Heinz Saathoff <hsaat bre.ipnet.de> writes:
Kiyuki schrieb...
 Code fragment of this sample:
 
 hi = ((code/0x100) - 0x98) & 0xff; (1)
 lo = code & 0xff;                  (2)
 if (0x40 <= lo && lo < 0x7f) { ... (3)
 
 Statement (1) is compiled to
 
   mov SI,CX
   mov CX,8
   shr SI,CL
   add SI,0xff68h
   and SI,0ffh

Till here it's ok you say.
 It seems good, indeed. But register CX is changed to 8; so 
 the value of the variable code is 8 which I don't expected.
 
 Statements (2), (3) are compiled to
 
   mov BX,CX
   xor BH,BH
   cmp BX,040h
   jb L65
   cmp BX,07fh
   jae L65 ...
 
 When this code runs, the variable lo is always 8, because 
 the register variable CX is assigned to 8.

You're right, haven't seen this in my previous post. This is indeed wrong code as CX isn't the value of 'code' anymore. It's a code generation or optimizer bug. Regards, Heinz
Jul 17 2001
parent "Walter" <walter digitalmars.com> writes:
It is a bug, and I've sent Kiyuki a fix. Next time I post a new version,
it'll incorporate the fix. -Walter

Heinz Saathoff wrote in message ...
Kiyuki schrieb...
 Code fragment of this sample:

 hi = ((code/0x100) - 0x98) & 0xff; (1)
 lo = code & 0xff;                  (2)
 if (0x40 <= lo && lo < 0x7f) { ... (3)

 Statement (1) is compiled to

   mov SI,CX
   mov CX,8
   shr SI,CL
   add SI,0xff68h
   and SI,0ffh

Till here it's ok you say.
 It seems good, indeed. But register CX is changed to 8; so
 the value of the variable code is 8 which I don't expected.

 Statements (2), (3) are compiled to

   mov BX,CX
   xor BH,BH
   cmp BX,040h
   jb L65
   cmp BX,07fh
   jae L65 ...

 When this code runs, the variable lo is always 8, because
 the register variable CX is assigned to 8.

You're right, haven't seen this in my previous post. This is indeed wrong code as CX isn't the value of 'code' anymore. It's a code generation or optimizer bug. Regards, Heinz

Jul 17 2001