Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Conpiler macht Mist: For schleife mit Falschen werten


Flamefire - Fr 31.07.09 16:47
Titel: Conpiler macht Mist: For schleife mit Falschen werten
Hi,
hab mal wieder feststellen müssen, dass mein Compiler (D2009) Mist macht.
Hab folgende Function:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
class procedure Tfoo.bar(var stream:byte8;key1:Cardinal;key2:Byte);
var i:Integer;
    key1a:Array[0..3of Byte;
begin
  PCardinal(@key1a[0])^:=key1;
  for i:=0 to 3 do
    stream[i]:=stream[i] XOR (stream[i]+key1a[i]+key2);
  for i:=4 to 7 do
    stream[i]:=stream[i] XOR (stream[i]+key1a[i-4]+key2);
end;

und was macht mir der Compiler aus der ersten Schleife von 0 bis 3?
Ein schleife von 4 bis 1!!! (Habs im ASM angeguckt)
Folge: RangeCheck Error!

Warum bitte das?
Wie kann ich das vermeiden?

EDIT: type byte8=array[0..7] of Byte; fehlte


Marc. - Fr 31.07.09 16:58

Ich hab's grad ausprobiert. Das liegt an der Optimierung vom Compiler. Wenn Du diese via {$O-} ausschaltest, klappt's einwandfrei. ;)
Warum der Compiler allerdings durch die Optimierung solch ein Fehlverhalten zeigt, ist mir ein Rätsel. :nixweiss:


Flamefire - Fr 31.07.09 17:05

its ja mal ganz toll...wenn man sich nicht auf den compiler verlassen kann...


Muck - Fr 31.07.09 17:22

Hallo,

ich habe die Funktion in Delphi 2009 getestet und die Function selbst mit Code optimierung funktioniert fehlerfrei.


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
Unit1.pas.31: PCardinal(@key1a[0])^:=key1;
0046423C 8BDC             mov ebx,esp
0046423E 8913             mov [ebx],edx
Unit1.pas.32: for i:=0 to 3 do
00464240 BE04000000       mov esi,$00000004                      // Schleife hat 4 Durchlaeufe
00464245 8BD0             mov edx,eax                            // edx ist offset zu key1a  
00464247 8BFC             mov edi,esp                            // edi ist offset zu stream
Unit1.pas.33: stream[i]:=stream[i] XOR (stream[i]+key1a[i]+key2);
00464249 0FB61F           movzx ebx,[edi]
0046424C 021A             add bl,[edx]
0046424E 02D9             add bl,cl
00464250 301A             xor [edx],bl
00464252 47               inc edi                                // naechstes byte fuer stream
00464253 42               inc edx                                // neachstes byte for key1a
Unit1.pas.32: for i:=0 to 3 do
00464254 4E               dec esi                                // esi --
00464255 75F2             jnz $00464249                          // wenn nicht null weitermachen


das ist alles fehlerlost, kein Fehler im Compiler.
Die Optimierung berechnet die Differenz des Schleifenzaehlers (ESI 4) und nutzt andere Register fuer den Index auf Arrays. Die Variable I gibt es nicht wirklich waehrend des Schleifendurchlaufs.

Markus


Flamefire - Di 04.08.09 19:53

hm ok...dann hab ich mich vermutlich von esi irritieren lassen, und der anzeige von i=4 im debugger