لماذا سجل 16 بت تستخدم مع تعليمات BSR في هذه التعليمات البرمجية المتكررة؟

StackOverflow https://stackoverflow.com/questions/1818374

  •  10-07-2019
  •  | 
  •  

سؤال

في هذه المادة المتشددين هناك find_maskwidth() وظيفة يكشف أساسا عدد البتات المطلوبة لتمثيل القيم dictinct itemCount:

unsigned int find_maskwidth( unsigned int itemCount )
{
    unsigned int maskWidth, count = itemCount;
    __asm {
        mov eax, count
        mov ecx, 0
        mov maskWidth, ecx
        dec eax
        bsr cx, ax
        jz next
        inc cx
        mov maskWidth, ecx
    next:
    }
    return maskWidth; 
} 

والسؤال هو لماذا لا تستخدم ax وcx يسجل بدلا من eax وecx؟

هل كانت مفيدة؟

المحلول

وأنا لا يمكن إلا أن يخمن أنها تتوقع أن نتعامل الا من أي وقت مضى مع الحقول التي لديها ما لا يزيد عن 16 بت. منذ يتم استخدامه لتحديد عدد البتات التي يمكن استخدامها لتقرير الأمور مثل عدد النوى أو المعالجات المنطقية في حزمة أنه سوف ربما يكون بعض الوقت قبل أن تفيض فوق 65535.

وآمل فقط شخص لا تقرر استخدام روتين لغرض أعم.

ومجرد لمعلوماتك - إذا كنت تريد أن تفعل شيئا من هذا القبيل دون أن يخسر في التجمع إلى x86 (على الرغم من أنني أعتقد لأغراض هذه المادة، ويجري غير المحمولة هو الى حد كبير نظرا ل)، في بت الصفحة Twiddling المأجورون كنت قد غطت.

نصائح أخرى

وأعتقد أن البيانات الأصلي هو فقط 16-بت واسعة. منذ CX هو الحصول على عدد بعض الشيء، ليس هناك فرصة أنه يمكن أن يكون أكبر من عدد صغير جدا على أي حال.

ومن المثير للاهتمام أن نلاحظ أنه في مستوى واحد من أكواد العمليات للحصول على تعليمات IA32 16 بت و 32 بت هي نفسها باستثناء البايت البادئة، لذلك هو أكثر كفاءة لإصدار كل 32 أو كل 16 تعليمات قليلا، اعتمادا في الوضع الذي هي فيه. أعتقد أن هذا هو السبب الذي طرح السؤال ...

ونظرا لحقيقة أن هذا الرمز هو حقا حقا سوء كتابة (ليست هناك اي حاجة لmaskWidth وعدد المتغيرات، على سبيل المثال - بصرف النظر عن جعل رمز الخلط) أعتقد يمكنك أن تطمئن إلى أنه مجرد " شيئا سيئا "في هذا القانون.

وروتين يحدد bascially ثنائي اللوغاريتم (قاعدة اثنين) من البالغ عددها ITEMCOUNT.

ووسيلقي قيم خاطئة كلي، إذا البالغ عددها ITEMCOUNT> 2 ^ 16. أنها لا تشبع أو شيء من هذا، بل هو مجرد خطأ. المعلمة الإدخال "صحيح غير الموقعة"، مما يجعله أكثر خطأ. لذلك سوف تتوقف عن العمل في أكثر من 65536 النوى.

وتخميني هو، حفرت شخص في إنتل بعض قطعة القديم حقا من التعليمات البرمجية، التي يعود تاريخها إلى 16 مرة بعض الشيء، من دون فهم حقا عليه، واستخدامه، لأن 65536 سوف يكون كافيا إلى الأبد، تماما كما 640K الذاكرة سوف يكون كافيا إلى الأبد أو من رقمين أرقام العام لن يكون كافيا حتى نهاية الوقت.

وانا اقول انها لمؤلف هذا الرمز ربما لم يعرف حقا ما كان يقوم به :-). إصدارات 16 بت من هذه التعليمات هي لفترة أطول، وليس أي أسرع. في الواقع، فإنها ربما تسبب كشك تسجيل جزئي على التعليمة التالية التي تستخدم ECX (بمعنى MOV).

ونلاحظ أيضا أن القفزة يمكن أن يكون بأمان انتقل تعليمة واحدة في وقت سابق (بعد DEC)، كما ديسمبر يحدد بالفعل ZF عندما انتاجها هو صفر. هذا يمكن تبسيط رمز قليلا.

وهكذا هذا هو كيف لي أن أكتب هذه التعليمات البرمجية المتكررة:

  mov eax, [count]
  xor ecx, ecx
  dec eax
  jz next
  bsr ecx, eax
  inc ecx
next:
  mov [maskWidth], ecx

وكما أن الدافع لاسقاط في التجمع هنا يبدو أن استخدام تعليمات BSR، التي ليس لديها أي ما يعادل باللغة C أو مكتبة. يمكنك تجنب استخدام التجميع باستخدام وظيفة جوهرية مترجم خاص لهذا الغرض. في حين أن هذه هي nonportable بطبيعتها، لا هو تجميع المضمنة.

في دول مجلس التعاون الخليجي وظيفة معادلة قد تبدو هذه:

unsigned int find_maskwidth(unsigned int itemCount)
{
   if(itemCount <= 1)
      return 0;
   else
      return 32 - __builtin_clz(itemCount - 1);
}

وأكثر من ذلك بكثير للقراءة، أليس كذلك؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top