/Into the Low Level: Assembling (0x06)

Into the Low Level: Assembling (0x06)

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

فى المقاله السابقة تحدثنا عن استدعاء النظام exit. ومن حيث توقفنا سأستكمل الحديث ولنبدأ ب استدعاء النظام write.

استدعاء النظام write ينقل او بمعني اخر ينسخ البيانات من مكان فى الذاكره الى اي مكان اخر، فهؤلاء مبرمجي لغه السي يعملوا كيف يعمل استدعاء النظام write تحت لغه السي. ولكن فى سبيل الوضوح فهو يبعث بنسخه من البيانات من المصدر الى المستقبل، ويختلف المستقبل من حيث كونه الشاشه( الخرج القياسي / Standard Output) او مقبس فى الشبكه (سوكيت / Socket) او ملف او أي كان هذا الخرج. فهو يمثل يعتبر كأنبوبه تصل المصدر بالخرج إذا جاز التعبير.

كما استدعينا exit فى المقاله السابقة عن طريق وضع رقم فى ال Eax. سنفعل المثل مع كل الاستدعاءات؛ فأستدعاء النظام Write رقمه 4. وكما وضعنا الرقم صفر فى ال EBX فى استدعاء النظام exit لنفيد بخروج البرنامج بدون اي اخطاء. سنضع رقم ال Descriptor او الواصف فى ال EBX فى استدعاء النظام Write. اما مصدر وحجم البيانات فسنضعها فى ECX وEDX على التوالي.

وهنا نأتي الى تساول. من اين أاتي بتلك البيانات التى اريد طباعتها، فى لغه البرمجه على سبيل المثال تضع اي نص فى متغير وتكتفي بطباعه المتغير الذي يشير الى النص بدوره. الامر لا يختلف كثير فى لغه التجميع ولكن فى لغه التجميع هنالك مايسمي بالاقسام وفيه يتم تقسيم البرنامج الى الاقسام التى ذكرتها فى مقالاتي السابقه وهم (قسم الكود – قسم البيانات – قسم التخزين/الستاك).

فى الكود يتم تقسيم البرنامج كالتالي

اما كتابه المتغيرات وتحديد حجمها فيتم عن طريق كلمات محجوزه مثل db – dw – dd والتي تعني data byte – data word – data double word.

تأمل طريقه كتابه البرنامج التالي قبل ان تقرأ مابعد الكود

لنبدا بقسم البيانات، يوضع اسم المتغير (هو ليس متغير ولكن أقول متغير على حد التعبير ولكنه يسمي عنوان او ليبل) قبل النقطتين الرأسيتين ثم يوضع حجم المتغير ثم قيمتها. وفى اول متغير (str) نلاحظ ان حجم المتغير بايت واحد ولكن قيمته تتعدي هذا بكثير. وهنا نحتاج الى تحديد حجم النص. اما الرقم 10 او A فهو حرف نهايه السطر \n.

اما strlen فنضع داخلها قيمه حجم النص لنتمكن من تنفيذ العمليات على النص كامل ويلاحظ اننا استخدمنا EQU، وهنا نأتي الى نقطه التوجيهات او التعليمات، هناك توجيهات من شأنها تنفيذ عمليات معينه مثل ORG وINCLUDE والعديد

اما التوجيه EQU فهو يضع قيمه رقمية داخل الليبل او العنوان المحدد وفى حالتنا تلك فهو يضع حجم ال str. اما $ فهي تعني مكان التنفيذ الحالي فإذا كان مكان الأمر الذي سينفذه فى الذاكره هو 0x1A على سبيل المثال ف العلامه $ تعني نفس القيمه. لذا فإن $ تعني مكان strlen فى الذاكره وبما أنه يتبع str مباشرة فهذا يعني ان فرق العنوان بينه وبين str هو عدد الحروف الموجود فى النص. لذا فإن ناتج طرح مكان strlen ومكان str يعني طول النص.

اما فى قسم الكود فإننا نعرف مايسمي بنقطة بداية التنفيذ عن طريق global ثم اسم العملية التى ستنفذ وهنا هي _start. ثم نبدأ الكود بأسم العمليه وبعدها نقطتين رأسيتين لتحديد بداية العمليه، ثم نكتب الكود وهو كما ذكرت مسبقا طباعة النص ومن ثم الخروج.

فى البدايه فإننا نضع رقم استدعاء النظام فى الريجستر EAX و نضع رقم ال Descriptor فى الريجستر EBX والشاشه او الخرج القياسي رقم الواصف او الدسكريبتور الخاص به هو 1 وهى تمثل الهدف الذي ستنقل له البيانات. اما ecx فيوضع داخله str، وهنا لايمثل str النص بل يمثل عنوان بداية النص لذا فأن القيمه التى سيتم وضعها فى ecx هو عنوان بداية النص، اما edx فنضع داخله قيمه حجم النص وهنا strlen لايساوي العنوان الذي يشير الى حجم النص بل هو قيمة رقميه مباشرة.

بعد ذلك ننفذ انتربت او قاطع  80  الذي تحدثنا عنه مسبقا  ليتم تنفيذ  استدعاء النظام ،  وبعد ذلك  ننفذ  استدعاء النظام  exit  لنتمكن  من الخروج من البرنامج .  وبعد ذلك نجمع البرنامج بالمجمع nasm كما فعلنا المره السابقة.

ولكن فى تلك المرة سوف نضع البرنامج فى debugger لمراقبة التنفيذ لذاسيكون الامر كالتالي:

nasm -f elf -g -F stabs source.asm.

ونربط البرنامج باللينكر ld كالمرة السابقة.  ld -o output source.o وننفذه .

الحقت فيديو بالمقال فيه شرح تفصيلي لطريقة تنفيذ وتصحيح ومعالجة الكود. (يمكن تحميل الفيديو من هنا)

اما التعليق الذي وعدت بيه فى بداية المقال علي التربو اسمبلر فهو لعلمي ان كثير ممكن يقرؤن المقاله يعلمون كيفيه البرمجه بالتربو اسمبلر وذلك لاسباب اكاديميه بالطبع؛ لكن على اي حال فإن التربو اسمبلر يستخدم مايسمي بال DOS interrupts وهى ذات الرقم 21h وهى ترجع لعصر ال real modes حينما كان حجم الذاكره 64 كيلو بايت وميجا. وتنفيذها على الويندوز يحتاج الى VM86 كثيرا من الاحيان لعدم خضوعها لل protected mode. فهي فى بعض الاحيان يكون خرجها COM وهي ملفات تنفيذيه تستخدم قسم واحد وتخرق قاعدة التقسيم segmentation تحت ال protected mode ايضا. كما ان لغه التجميع المستخدمه حاليا تحت الويندوز هي MASM ميكروسوفت اسمبلر وهى مايراه ويستخدمه تقريبا جميع من يقوم بالهندسه العكسيه تحت الويندوز وفيها تتم استدعاءات النظام من خلال الاستدعاءات الموجوده بالمكتبه kernel32.dll او مكتبات اخري.. وسوف ايضا نتطرق الى التجميع تحت الويندوز ولكن بعد فتره.

كما ان لغه التجميع هى اقوي واهم وام جميع اللغات فهي لغة الماكينه فلانحد التفكير فيها على انها تطبع او تستقبل حروف فهي لم تخترع لهذا الهدف ولكن طباعة واستقبال النصوص والارقام هو عرض لمدي ديناميكيه لغة التجميع. كما ان اي مطور اكسبلويت(هاكر) او مهندس عكسي(هاكر برضة) يجب ان يعرف التجميع وتقنيات تنفيذه تحت نظم التشغيل المختلفة. علي اي حال… القاكم بالمقال القادم.