Tutorial 1: الاساسيات على قارء هذا الدرس ان يكون على درايه بالاداة MASM. إذا لم يكن القارء الكريم يعرف الاداة MASM يمكنك تحميل ودراسة النص المرفق داخل الحزمه قبل ان تستمر فى قرئه باقى الدرس. نظري: برامج الـWin32 تعمل فى النمط المحمي هذا النمط موجود منذ صدور المعالج 80286. ولكن المعالجات من نوع 80286 قد إنقرضت, لذلك لن نشغل انفسنا سوى بالمعالجات من نوع 80386 فما بعدها. كل برنامج win32 من برامج الوندوز يعمل فى مساحه وهميه منفصله فى الذاكره, هذا يعنى ان كل برنامج من برامج win32 سوف يحصل على عنوان مساحه مقدارها 4GB فى الذاكره. ولكن هذا لا يعنى ان كل برنامج من برامج Win32 لديه إمكانية الحصول على 4GB من الذاكره الفعليه, وإنما يعنى ان كل برنامج يستطيع ان يحصل على مؤشر لاي عنوان فى هذا النطاق. بالطبع نظام وندوز يحاول عمل ما فى وسعه لجعل مؤاشرات الذاكره التى يرغب البرنامج فى إستخدامها صالحه, ولكن على البرنامج ايضاً ان يلتزم بالقواعد التى يضعها نظام وندوز, وإلا فإنه سوف يتسبب فى الخلل العام للحمايه (General Protection Fault). على عكس برامج Win16 فإن كل برنامج من برامج Win32 يتواجد وحده فى الذاكره المخصصه له. جميع برامج Win16 تستطيع ان *ترى* بعضها البعض, ولكن الامر ليس كذلك بالنسبه لبرامج Win32. هذه الخاصيه تساعد على التقليل من إمكانية ان برنامج يقوم بالكتابه فى بيانات (data) او شيفرة (code) برنامج اخر. تنسيق الذاكره ايضاً يختلف فى نظام Win32 تمام الاختلاف عنه فى نظام الـ16-بت, ففى نظام Win32 لا نحتاج ان نشغل انفسنا بتنسق الذاكره او الازاحه (segment)كما كان الحال فى النظام السابق, الان يوجد فقط تنسيق واحد للذاكره وهو مايسمى بالتنسيف المسطح للذاكره (Flat memory model), والان ليس هناك تحديد لمساحة الازاحه بـ64K كما كان الحال فى السابق. الذاكره الان اصبحت مساحه كبيره ومتصله بحجم 4GB, وهذا يعنى اننا لسنا بحاجه للتعامل المباشر معى مسجلات الازاحه(segment registers). هذه العوامل هى التى تجعل برمجة الاسمبلى فى بيئة Win32 تصبح بنفس سهولة البرمجه فى لغة السى. عندما تقوم بعمل برانامج فى بيئة Win32 عليك ان تعى بعض القوانين الهامه, احد هذه القوانين هو ان نظام وندوز يستخدم المسجلات esi, edi, ebp و ebx إستخدام داخلى ولا يتوقع ان يحدث اى تغير لقيم هذه المسجلات, لذلك تذكر هذه القاعده اولاً: إذا استخدمت احد هذه المسجلات فى داله من دوال الاستدعاء (callback function) لا تنسى ان تعيد للمسجل قيمته الاصليه قبل ان تعيد التحكم لنظام الوندوز. دوال الاستدعاء (callback function) هى الدوال التى قمت ببرمجتها والتى يتم إستدعائها من قبل وندوز. المثال الواضح لمثل هذه الدوال هى دالة الوندوز (windows procedure). هذا بالطبع لا يعنى انك لا تستطيع إستخدام هذه المسجلات, فقط تذكر انك إذا قمت بإستخدامها عليك ان تعيد لها قيمتها الاصليه قبل ان تعيد التحكم لنظام وندوز. المحتوى: لنطلع الان إلى هيكل برنامج, إذا استعصى عليك فهم الشفره بالكامل فلا تقلق, ساقوم إن شاء الله بتقديم شرح كامل لاحقاً. دعنا الان نقوم بتحليل كامل لهيكل البرنامج. هذه الشفره هى بمثابة موجه لمترجم الاسمبلى (assembler directive) تخبر المترجم بان عليه ان يستخدم مجموعة تعليمات المعالج من نوع 80386. تستطيع ايضاً ان تحدد معالجات من نوع 486., 586. ولكن من الاحوط ان تلتزم بإستخدام 386. هناك فى الواقع نوعين شبه متطابقين لكل معالج , .386p/.386, .486/.486p. المعالجات التى تحمل علامة الـ "p" تحتاجها فقط عندما تريد من برانامجك ان يستخدم الاوامر ذات الصلاحيات الخاصه (privileged instructions), الاوامر ذات الصلاحيات الخاصه هى اوامر مجوزه من قبل المعالج او نظام التشغيل عندما يعمل فى النمط المحمى (protected mode). هذا النوع من الاوامر يستخدم فقط من قبل شفره ذات صلاحيات خاصه, على سبيل المثال المعرف الوهمى للاجهزه (virtual device drivers). فى اغلب الحالات برامجك ستعمل بدون إستخدام الاوامر ذات الصلاحيات الخاصه, لذلك تستطيع ان تستخدم الموجهات العاديه والتى لا تنتهى بحرف الـp. هذا ايضاً موجه ومهمته تحديد نوع الذاكره التى تريد إستخدامها فى برنامجك, تذكر ان هناك نوع واحد فقط من تنسيق الذاكره فى نظام Win32 الا وهو النوع المسطح (FLAT model). هذه الداله تخبر MASM عن طريق إرسال المتغيرات, طريقة إرسال المتغيرات تحدد الترتيب الذى ترسل به المتغيرات وهى إما من اليمني إلى اليسار او العكس, وايضاً من هو المسؤل على المكدس بعد الإنتهاء من الداله التى تم إستدعائها, فى نظام Win16 توجد طريقتين للإستدعاء, إحداهما هى طريقة السى والاخرى هى طريقة الباسكال. فى طريقة السى ترسل المتغيرات من اليمين إلى اليسار, يعنى نقوم بوضع المتغير الموجود فى اقصى اليمن فى المكدس اولاً ثم الذى يليه وهكذا..الداله التى قامت بالإستدعاء هى المسؤله عن إعادة توازن المكدس بعد ان يعود إليها التحكم. على سبييل المثال إذا اردنا إستدعاء داله إسمها: (foo(int first_param, int second_param, int third_param بطريقة لغة السى فشيفرة الاسمبلى ستصبح على النحو التالى: طريقتها هى العكس تماماً بالنسبة لـ لغة السى ترسل المتغيرات من اليسار إلى اليمين والداله التى تم إستدعائها هى المسؤله عن إعادة التوازن للمكدس بعد الانتهاء. WIN16 تتبنى طريقة فى الاستدعاء لانها تنتج شيفره بحجم اصغر, طريقة السى افضل إذا لم يكن لديك علم مسبق بعدد المتغيرات التى تستخدمها داله معينه, مثل فى حالة الداله ()wsprintf. فى حالة ()wsprintf لا تستطيع الداله باى حال من الاحوال تحديد عدد المتغيرات التى سوف تحصل عليها من خلال معرفة عدد الدوال التى وضعت فى المكدس, وبذلك لن تستطيع القيام بإعادة توازن المكدس بعد الانتهاء. هى خليط من و ترسل المتغيرات من اليمين إلى اليسار ولكن الداله التى تم إستدعائها هى المسئوله عن إعادة توازن المكدس. منصة Win32 تستخدم فقط. إلا فى حالة ()wsprintf يجب عليك إستخدام طريقة فى الاستدعاء معى الداله ()wsprintf. هذه الاربع دوال هى موجهات لمترجم الاسمبلى وتدعى اقسام او تقسمات (section). تذكر دائماً انه لا يوجد إزاحات (segments) فى نظام Win32, ولكن يمكنك تقسيم عناوين الذاكره المخصصه لبرنامجك تقسيماُ منطقياً, بداية قسم معين تدل على نهاية القسم الذى قبله. هناك مجموعتين من الاقسام, قسم البيانات (data) و قسم الشفره (code), قسم البيانات مقسمه إلى ثلاث اقسام على النحو التالى: هذا القسم يحتوى على تعريف بالبيانات الحاصله على قيمه مبدئيه . هذا القسم يحتوى على تعريف بالبيانات ذات القيمه المبدئيه, فى بعض الاحيان نريد ان نحجز جزء من الذاكره دون ان نضع لها قيمه مبدئيه, وذلك هو هدف هذا القسم. الفائده من البيانات التى لاتحوى قيمة مبدئيه هى انها لا تحجز مكان فى الملف التنفيذى, على سبيل المثال إذا قام برنامجك بحجز 10000 بايت فى قسم الــ?DATA. فلن بحتوى برنامجك على 10000 بايت فى هذا القسم, وإنما يبقى بنفس الحجم, البرنامج فقط يخبر المترجم بحجم المساحه التى يحتاجها البرنامج فى الذاكره عندما نقوم بتشغيله فقط لا غير. هذا القسم يحتوى على تعبريف بالقيم الثابته التى سوف يستخدمها برنامجك. الثوابت فى هذا القسم لا يمكن ابداً تغيرها فى برنامجك, هى فقط مجرد *ثوابت*. لست مجبر على إستخدام جميع هذه الاقسام الثلاثه فى برنامجك, عرف فقط الاقسام التى تحتاجها. هناك قسم واحد فقط للشفره : وفيه تضع شفرة برنامجك. و هى اى اسم اختياري وهى لتحديد مجال شفرة البرنامج, شرط ان يكون الاسمين متطابقين. شيفرة البرنامج بالكامل يجب ان بين و تنتهى بى