الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

طرق متعدده لتقسيم الدوال مثل lparam فى الاسمبلى

مغلق
بدأه احمد غريب في 7 يونيو 2005 · 0 رد · 1,629 مشاهدة · في لغة Assembly لأنظمة 16, 32, 64 بت
مشاركة: واتساب X فيسبوك تيليجرام
#1

السلام عليكم

عندما بدات تعلم الاسمبلى وبرمجه الAPI كانت هناك طريقة يستخدمها اغلب مبرمجى الاسمبلي فى الحصول على الجزء الادنى من الدوال امثال lParam و wParam, هذه الطريقه كانت تزعجنى جداً ولكن لقلة خبرتى فى الاسمبلى لم يكن لدى القدره على تغير الامر وكنت انصاع لهذه الطريقه لانى لا اعرف غيرها, ولكن بعد فتره وجدت مقاله كتبها شخص إسمه Ernie يوضح فيها كيفيه تغير هذه الطريقة وإستخدام طريقه افضل دعونى اضع مثال حتى تتضح الصوره.

مثال:

عندما تريد على سبيل المثال ان تقراء مدخلات الماوس من دالة lParam فإنك تقوم بالتالى:

.ELSEIF uMsg==WM_LBUTTONDOWN
  mov eax,lParam
  and eax,0ffffh
    mov ebx,lParam
  shr ebx,16

وبذلك تحصل على موقع x فى eax وموقع y فى ebx , هذه هى الطريقه التى تعلمناها وتعودنا عليها, ونستخدمها فى حالات كثيره جداً فى برمجة الAPI .

طبعاً Ernie لم تعجبه الطريقة وشكى الموضوع لhutch الرجل الذى يحمل على عاتقه تطوير مكتبات masm32 فاشار عليه بالتالى.

البديل الاول

قم باخذ المعطيات من الستاك مباشرتاً بدلاً من تقسمها بهذه الطريقه المطوله وإليك مثال يوضح ذلك:

    wParamL equ <WORD PTR [ebp + 16]>
    wParamH equ <WORD PTR [ebp + 18]>
    lParamL equ <WORD PTR [ebp + 20]>
    lParamH equ <WORD PTR [ebp + 22]>

وبهذا تستطيع إختصار الكود الاصلى على النحو التالى:

.ELSEIF uMsg==WM_LBUTTONDOWN
  mov eax,lParamL
      mov ebx,lParamH

طيب جميل جداً ولكن المشكله ان الجزء الاول من الكود معقد جداً ولا استطيع ان اذكر مواقع الدوال فى الإٍستاك, ولنفرض اننى اردت ان استخدم دوال اخرى غير الlParam و wParam فهذه الطريقة غير مجديه, رغم انها اختصر على صطرين من الشفره.

البديل الثانى

Ernie لم يقتنع بالحل وقرر إيجاد حل اخر وهو على النحو التالى:

packedDW UNION
    value DWORD ?
    STRUCT
        loword WORD ?
        hiword WORD ?
    ENDS
packedDW ENDS

كما تلاحظو طريقة Ernie مبنية على تحديد متغير من نوع جديد يمكننا من الوصول إلى كل word فى المتغير او نستطيع ان ناخذ DWORD ولن نستهلك الذاكره لاننا نستخدم UNION والمثال يصبح على النحو التالى:

.ELSEIF uMsg==WM_LBUTTONDOWN
  mov eax,lParam.loword
      mov ebx,lParam.hiword

فى بادء الامر اعجبت بهذه الطريقه وطورتها لاجعلها اكثر شمولاً حيث انه يمكن تقسم الDWORD إلى 4 byte على النحو التالى:

packedDW UNION
    value DWORD ?
    STRUCT
        loword WORD ?
        hiword WORD ?
    ENDS
STRUCT
        llbyte byte ?
        lhbyte byte ?
hlbyte byte ?
hhbyte byte ?
    ENDS
packedDW ENDS

وبهذا استطيع الوصول إلى كل بايت او كل word او dword بنفس الطريقه السابقه, ولكن عندما اردت تطبيق الطريقه لاحظت اننى لابد ان اغير طريقتى فى البرمجه وتغير جميع الدوال من نوع dword إلى packedDW, ليس فقط ذلك ولكن لاحظت ايضاً ان برامجى اصبحت تشبه برامج السى بلس بلس, وشعرت كانى لا اعرف هذه اللغه وقررت ان ابحث عن طريقه افضل..

البديل الثالث

فى بعض الاحيان نعقد الامور بدلاً من تبسيطها ونبحث عن حلول لتبسيط امور هى فى الاصل بسيطه, يوجد دوال فى معالج Intel يقوم بما نريد دون الحاجه لإستخدام Shitft او AND ودون الحاجه إلى تغير الدوال وذلك على النحو التالى:

movzx eax, word ptr[lParam] 
movzx ebx, word ptr[lParam+2]

شكل البرناج لم يتغير ولن يحدث خلل فى باقى البرنامج لان هذه العمليه هى نفس العمليه التى تعودنا عليها ولكن بطريقه مختصره وتصلح معى جميع انواع المتغيرات, يمكنك ان تجرب الطريقه على النحو التالى.

إذهب إلى ملف ICZTUTES الموجود تحت ملف masm32 ثم افتح الدرس رقم 7 فى الغالب المسار سيكون على النحو التالى إذا قمت بتنصيب برنامج masm32 بالطريقه المعتاده

C:\masm32\ICZTUTES\TUTE07

افتح ملف الاسمبلى mouse.asm وغير الجزء التالى:

.ELSEIF uMsg==WM_LBUTTONDOWN
  movzx eax,lParam
  and eax,0ffffh
  mov hitpoint.x,eax
  movzx eax,lParam
  shr eax,16
  mov hitpoint.y,eax
  mov MouseClick,TRUE
  invoke InvalidateRect,hWnd,NULL,TRUE

بحيث يصبح على النحو التالى

.ELSEIF uMsg==WM_LBUTTONDOWN
  movzx eax,word ptr[lParam]
  mov hitpoint.x,eax
  movzx eax,word ptr[lParam+2]
  mov hitpoint.y,eax
  mov MouseClick,TRUE
  invoke InvalidateRect,hWnd,NULL,TRUE

قم بعملية كمبايل ولنك للبرنامج وسوف تلاحظ ان البرنامج يعمل وان ما قمنا به ماهو إلا تسريع للبرنامج, بالطبع لن يكون هناك فرق ملحوظ للسرعه ولكن تخيل لو كان البرنامج يقوم بهذه العمليه 1000 مره او 100000 مره عند إذا سيكون الفرق ملحوظ.

وبالتاكيد لم اضع هذا الموضوع لانى اتضايق من سرعة مثل هذا البرنامج ولكن لانى اريد ان اعود نفسى على كتابة البرامج بالطريقه الصحيحه.

إذا ارتم ان تقراؤ موضوع Ernie والذى كان السبب فى كتابتى لهذا الموضوع فهو موجود على الرابط التالى :

http://ourworld.compuserve.com/homepages/e...orld/params.htm

اسف على الاطاله

والسلام عليكم

لا إله إلا الله محمد رسول الله

busbar : يجب ان تدرك انه هناك حد ادنى للمعرفة المطلوبة قبل البدء في عمل أي شئ.

هذا الموضوع مغلق.

مواضيع مشابهة