piątek, stycznia 07, 2011

Spektakularny bug w GCC





80483fd: c7 04 24 30 85 04 08 movl $0x8048530,(%esp)
8048404: e8 1b ff ff ff call 8048324
8048409: dd 5c 24 18 fstpl 0x18(%esp) //zdjęcie wyniku ze stosu fp
804840d: c7 04 24 32 85 04 08 movl $0x8048532,(%esp)
8048414: e8 0b ff ff ff call 8048324
8048419: dd 44 24 18 fldl 0x18(%esp) //załadowanie na stos fp
804841d: de f1 fdivp %st,%st(1) //dzielenie ST(0)=ST(0)/ST(1)
804841f: dd 5c 24 20 fstpl 0x20(%esp) //zdjęcie wyniku 1.0/3.0
8048423: c7 04 24 30 85 04 08 movl $0x8048530,(%esp)
804842a: e8 f5 fe ff ff call 8048324
804842f: dd 5c 24 28 fstpl 0x28(%esp)
8048433: c7 04 24 32 85 04 08 movl $0x8048532,(%esp)
804843a: e8 e5 fe ff ff call 8048324
804843f: dc 7c 24 28 fdivrl 0x28(%esp) //dzielenie ST(1)=ST(1)/ST(0)
8048443: dd 44 24 20 fldl 0x20(%esp)
8048447: d9 c9 fxch %st(1)
8048449: df e9 fucomip %st(1),%st // porównanie ST(0) z ST(1)
804844b: dd d8 fstp %st(0)
804844d: 0f 97 c0 seta %al
8048450: 0f b6 d0 movzbl %al,%edx
8048453: b8 34 85 04 08 mov $0x8048534,%eax
8048458: 89 54 24 04 mov %edx,0x4(%esp)
804845c: 89 04 24 mov %eax,(%esp)

Dzielenie fdivrl to dzielenie o podwójnej precyzji obliczeń (wynik ma typ double), podczas gdy fdiv to dzielenie o pojedyńczej precyzji. Obie operacje na takich samych argumentach zwrócą inne wyniki numeryczne. No i masz babo placek.

0 komentarze: