002
29.04.2005, 23:40 Uhr
~CDW
Gast
|
ich kann zumindest sagen dass es bei mir auf msvc++ 6.0 genau dasselbe Verhalten ist.
Woran das liegt: ich weiß nicht wie genau sich msvc++ 6 AutorenEdition an standards hält, also ohne gewähr und nur auf Windows und eine x86 CPU bezogen:
bei unsigned char wird intern trotzdem ein 32-bit register benutzt. der "vergleich" wird in etwa so übersetzt: Wenn ergebnis kleiner oder gleich 0 springe zu NEIN.
Code: |
SUB EAX,ECX TEST EAX,EAX JLE SHORT threadpr.00401045 00401025 |.PUSH threadpr.004018F0 0040102A |. 68 A0C04000 PUSH threadpr.0040C0A0 ; ASCII "Ja" 0040102F |. 68 68CD4000 PUSH threadpr.0040CD68 00401034 |. E8 F7000000 CALL threadpr.00401130 00401039 |. 83C4 08 ADD ESP,8 0040103C |. 8BC8 MOV ECX,EAX ; | 0040103E |. E8 CD000000 CALL threadpr.00401110 ; \threadpr.00401110 00401043 |. EB 1E JMP SHORT threadpr.00401063 00401045 |> 68 F0184000 PUSH threadpr.004018F0 0040104A |. 68 A4C04000 PUSH threadpr.0040C0A4 ; ASCII "Nein"
|
hier ist wohl die "Übersetzungsschablone" für Größer/Kleiner vergleich des compilers schuld, denn an sich ist es ja nicht falsch "wenn a-b kleiner gleich 0 dann gehe zu NEIN", Deine Bedienung wird einfach negiert. Dummerweise werden aber auf einer x86 CPU beim Überlauf die S,C (sign, carry) gesetzt. Carry signalisiert dabei die Überschreitung des Wertes. Im Register steht auch 0FFFFFFF0h. TEST ist verinfacht eine "optimierte" Methode um zu schauen ob das "ergebnis" 0 sei. Es setzt den Zeroflag auf 1 wenn das Ergebnis 0 ist. ABER: JLE(jump less or equal) springt wenn S!=0 oder Z=1 (Zeroflag, wenn das Ergebnis nach einer Operation 0 ist).
Und S(ign)- Flag wird bei einem SUB unabhängig davon gesetzt ob die Variable im Compiler als signed oder unsigned deklariert wurde (weil die CPU nix davon weiß )
Hier liegt also IMHO ein Compilerfehler bzw. Bug vor. Wenn nämlich die übersetzungsschablone genauso übersetzten würde wie es im Quellcode steht, würde hier ein "JA" kommen da das ergebnis doch deutlich über null liegt . Denn dass der S-Flag bei einem SUB gesetzt wurde nicht erst mit dem P4 eingeführt genauso wie die auswirkungen von TEST...
Bei dem zweiten Code wo ein unsigned int ist ist der code fast identisch:
Code: |
00401017 |. 2B45 F8 SUB EAX,DWORD PTR SS:[EBP-8] 0040101A |. 85C0 TEST EAX,EAX 0040101C |. 76 20 JBE SHORT threadpr.0040103E 0040101E |. 68 F0184000 PUSH threadpr.004018F0
|
es kommt wieder 0fffffff0h raus, dieselben Flags werden gesetzt, nur steht diesesmal "wenn grösser oder gleich gehe zu NEIN". Nun, das ist wieder so ein "optimization" Trick (nein, ich hatte kein optimization flag an beim compilieren, das bietet die Autrenedition gar net ) wenn da nämlich 0 wäre, würde der TEST den Zero-flag auf 1 setzen, und JBE springt wenn Z(ero)flag==0. Hier passts wieder mit der Bedienung.
Hoffe mal dass es etwas verständlich rüberkam.
Mich würde natürlich auch interessieren ob es "Bug or feature" ist. Was z.B gcc oder Inels Compiler dazu "sagen" würden. |