لماذا FLD1 تحميل نان بدلا من ذلك؟
-
26-09-2019 - |
سؤال
لدي وظيفة واحدة من الواحد C وهي مجرد return value * pow(1.+rate, -delay);
- يقوم بخصم قيمة مستقبلية على القيمة الحالية. الجزء المثير للاهتمام من التفكيك
0x080555b9 : neg %eax 0x080555bb : push %eax 0x080555bc : fildl (%esp) 0x080555bf : lea 0x4(%esp),%esp 0x080555c3 : fldl 0xfffffff0(%ebp) 0x080555C6: FLD1 0x080555c8 : faddp %st,%st(1) 0x080555ca : fxch %st(1) 0x080555cc : fstpl 0x8(%esp) 0x080555d0 : fstpl (%esp) 0x080555d3 : call 0x8051ce0 0x080555d8 : fmull 0xfffffff8(%ebp)
على الرغم من أن الحزب الواحد من خلال هذه الوظيفة ، يقول GDB (معدل 0.02 ، التأخير هو 2 ؛ يمكنك رؤيتها على المكدس):
(gdb) si 0x080555c6 30 return value * pow(1.+rate, -delay); (gdb) info float R7: Valid 0x4004a6c28f5c28f5c000 +41.68999999999999773 R6: Valid 0x4004e15c28f5c28f6000 +56.34000000000000341 R5: Valid 0x4004dceb851eb851e800 +55.22999999999999687 R4: Valid 0xc0008000000000000000 -2 =>R3: Valid 0x3ff9a3d70a3d70a3d800 +0.02000000000000000042 R2: Valid 0x4004ff147ae147ae1800 +63.77000000000000313 R1: Valid 0x4004e17ae147ae147800 +56.36999999999999744 R0: Valid 0x4004efb851eb851eb800 +59.92999999999999972 Status Word: 0x1861 IE PE SF TOP: 3 Control Word: 0x037f IM DM ZM OM UM PM PC: Extended Precision (64-bits) RC: Round to nearest Tag Word: 0x0000 Instruction Pointer: 0x73:0x080555c3 Operand Pointer: 0x7b:0xbff41d78 Opcode: 0xdd45
وبعد fld1
:
(gdb) si 0x080555c8 30 return value * pow(1.+rate, -delay); (gdb) info float R7: Valid 0x4004a6c28f5c28f5c000 +41.68999999999999773 R6: Valid 0x4004e15c28f5c28f6000 +56.34000000000000341 R5: Valid 0x4004dceb851eb851e800 +55.22999999999999687 R4: Valid 0xc0008000000000000000 -2 R3: Valid 0x3ff9a3d70a3d70a3d800 +0.02000000000000000042 =>R2: Special 0xffffc000000000000000 Real Indefinite (QNaN) R1: Valid 0x4004e17ae147ae147800 +56.36999999999999744 R0: Valid 0x4004efb851eb851eb800 +59.92999999999999972 Status Word: 0x1261 IE PE SF C1 TOP: 2 Control Word: 0x037f IM DM ZM OM UM PM PC: Extended Precision (64-bits) RC: Round to nearest Tag Word: 0x0020 Instruction Pointer: 0x73:0x080555c6 Operand Pointer: 0x7b:0xbff41d78 Opcode: 0xd9e8
بعد هذا ، كل شيء يذهب إلى الجحيم. تتجاوز الأمور بشكل صارخ أو مقومة بأقل من قيمتها ، لذلك حتى لو لم تكن هناك حشرات أخرى في محاولة Freeciv AI الخاصة بي ، فإنها ستختار كل الاستراتيجيات الخاطئة. مثل إرسال الجيش بأكمله إلى القطب الشمالي. (تنهد ، إذا كنت فقط كنت وصلت إلى هذا الحد.)
يجب أن أفتقد شيئًا واضحًا ، أو أعمى عن شيء ما ، لأنني لا أستطيع تصديق ذلك fld1
يجب أن تفشل من أي وقت مضى. حتى أنه يجب أن يفشل فقط بعد حفنة من التمريرات من خلال هذه الوظيفة. في مرور في وقت مبكر ، يتم تحميل FPU بشكل صحيح 1 في ST (0). البايتات في 0x080555C6 تشفر بالتأكيد fld1
- فحص مع x/... في عملية التشغيل.
ما يعطي؟
المحلول
مناسبة بشكل ملحوظ. ما لديك هنا هو مكدس فائض.
على وجه التحديد ، لقد فاضت أنت (أو ربما المترجم الخاص بك) مكدس X87. يمكن أن يحمل فقط 8 قيم ، وفي الوقت الذي fld1
تم إصداره ، وهو ممتلئ بالفعل (يشار إليه بكلمة علامة 0000
). وهكذا ، و fld1
يفيض المكدس (المشار إليه بواسطة IE, SF, C1
) مما يسبب النتيجة التي تراها.
حول سبب حدوث ذلك ، ربما تكون قد استخدمت تعليمات MMX دون استخدام EMMS
قبل استخدام تعليمات x87 ، أو أن المترجم الخاص بك يحتوي على خطأ ، أو لديك رمز تجميع في مكان ينتهك ABI من النظام الأساسي الخاص بك (أو مكتبة تستخدمها تنتهك ABI).
نصائح أخرى
يبدو أن لديك فائض مكدس FPU. كلمة علامة FPU هي 0 ، مما يعني أنه يتم استخدام جميع السجلات. يمكنك أيضًا رؤية جميع السجلات المحددة على أنها "صالحة" ، عندما أتوقع أن يكون البعض فارغًا.
لا أعرف لماذا سيحدث هذا. ربما لديك بعض رمز MMX الذي لا يصدر EMMS
تعليمات؟ أو ربما بعض التجميع المضمّن الذي لا يزيل المكدس بشكل صحيح؟