الأربعاء، 11 مايو 2016

- في البداية لنقم بتوضيح بعض الامور المتعلقة بالاسمبلي, فالاسمبلي من اقدم اللغات التي عرفها مجال البرمجة فهي تلي لغة الالة machine language في صعوبتها لكن في نفس الوقت تعد اسهل في التعامل من اجل التخاطب مع الحاسب, بكافة اجزائه.

فالناحية الاولى التي يتم ذكرها لمن يريد تعلم الاسمبلي هو مسالة التخاطب مع الاجهزة الملحقة بالحاسب.. من ميزات الاسمبلي:
1- السرعة في الاداة نظرا لان المجمع يقوم بتحويلها مباشرة الى لغة الالة.
2- الوضوح عند التنقيح حيث يمكن القول عن الشفرة المكتوبة بها بانها تتبع نظام What you write is what you get, اي ما تكتب تحصل عليه, ليس هناك اجرائيات تضاف من قبل المجمع كما في لغات اخرى مثل C او دلفي حيث يحمل اي تطبيق من عشرين سطر مئات وربما الالاف الاسطر البرمجية المقابلة في الاسمبلي وحدها فما بالك بمثل هذا على الكود المكتوب بلغة الالة.
3- قدرتها على الوصول الى كافة اجزاء الحاسب دون اي عائق امامها خصوصا فيما يتعلق بمسالة كتابة محركات drivers مثل محركات VxD او Sys .. التي يكون من المعقد جدا كتابتها في لغات مثل C مثلا لو لم تكن لديك الخبرة الكافية في التعامل مع العتاد البرمجي..
4- "المحمولية" او portability, فبامكان تطبيق الاسمبلي ان يعمل على اي نظام Windows دون اي اختلاف, المسالة فقط تتعلق بالمعالج المكتوب له التطبيق, فتطبيقات الاسمبلي التي تم التصريح عنها انها مكتوبة لمعالجات 386 مثلا سيكون بامكانها استخدام التعليمات الخاصة بمعالج 286 وماقبله بالاضافة الى تعليمات 386 لكن ليس بامكانها استخدام تعليمات اضيفت الى المعالج 486 (حتى لو كان الجهاز يحوي على هذا المعالج.. هذا الامر غير متعلق بتجهيزة جهاز الحاسب بالاصل لكنه متعلق بالناقلية التي سيتمتع بها هذا البرنامج)
وبما انه في يومنا هذا لم تعد تجد تجهيزات حاسوبية مدارة على معالجات اقدم من P3 فاذن يمكن فورا ان تقوم بالتصريح عن انك تريد ان تستخدم تعليمات المعالج 586 دون خوف.

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

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

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

ناحية اخرى وهي تتعلق بالصيفة المكتوبة لتعليمات الاسمبلي.. فعلى الرغم من تبسيطها لتكون بمثابة اختصارات لكلمات انكليزية معروفة تدل على معنى التعليمة الا ان "شكل" الكود المكتوب بلغة الاسمبلي قد يجعل المرء يخشى ان يبدأ بها, فمثلا تعليمة نقل البيانات mov, تعليمة الانتقال من عنوان لاخر jxx (xx تستبدل بحروف معينة تتبع تعليمة النقل هل هي شرطية اي مرتبطة بوقوع شرط معين ام غير شرطية مباشرة), تعليمة المقارنة cmp.. لاحظ كيف ان جميع هذه التعليمات تعبر عن كلمات انكليزية معروفة MOVE, JUMP, COMPARE, الخ
المسالة الوحيدة التي يجب الاهتمام بها فيما يتعلق بالتعليمات فضلا عن استخدامها هو الشروط المتعلقة باستخدام بعض التعليمات..

على سبيل المثال تعليمة النقل mov, لنفرض اني اريد ان انقل قيمة من عنوان في الذاكرة الى اخر, ليس من الممكن في هذه الحالة ان استخدم التعليمة بالشكل:


كود:


كود:
[FONT=Traditional Arabic][SIZE=4]mov   destination, source [/SIZE][/FONT]

الشكل السليم لهذا الامر هو ان اقوم بوضع عنوان المصدر source في احد المسجلات registers من ثم اقوم بالنقل.. بالشكل التالي:

كود:

كود:
[FONT=Traditional Arabic][SIZE=4]lea   register, source   ;  load effective address of "source" as data into "register" mov    destination, [register]; move data addressed by "register" to  "destination"[/SIZE][/FONT]


فاذن الموضوع ليس بالصعوبة المتصورة اذ بالامكان معرفة كل هذه الامور من خلال الاطلاع على ملف Intel opcodes المختصر الذي يوضح استخدام كل تعليمة بالاضافة الى سرد للتفاصيل المتعلقة فيها كشروط الاستخدام (من مسجل لموقع ذاكرة, من موقع ذاكرة لمسجل, من مسجل لمسجل ..) وبعض المعلومات المتعلقة بعدد البايتات الذي تحجزه (لو كنا مهتمين بمسالة حجم الملف النهائي) بالاضافة الى عدد دورات المعالج clocks (امور لا تلاحظها بالعين المجردة لكنها تظهر واضحة على التطبيقات الضخمة فالبرامج المكتوبة بلغات عالية المستوى تعاني من بعض البطئ المتعلق بالمعالجة مما يؤثر على فعالية التطبيق بينما لا تعاني تطبيقات الاسمبلي من هذا الامر على الاطلاق ان شاء الله بشرط الاستخدام الامثل للتعليمات وعدم الاكثار من عمليات مكررة او غير ضرورية كان بالامكان اختصارها ببعض سطور)




- بيئات البرمجة بالاسمبلي, 16, 32 و 64بت:


- الى هنا نكون قد انهينا بعض الافكار المتعلقة بالاسمبلي والتي تجعل الجدد متخوفين منها, ناتي الان الى ذكر الجزء المتعلق ببيئات الاسمبلي وهي الى الان ثلاثة: 16بت - 32بت - 64بت
بحق السماء ماذا يعني 16 او 32بت "anyway"!؟
ناتي هنا الى بعض المسائل المتعلقة بالعنونة وكيفية معالجتها من قبل المعالج processor, من المعروف ان المعالجات القديمة لم تكن تملك سرعات عالية كما هي عليه اليوم, لن ندخل في التفاصيل لكن فيما يتعلق بمسالة معالجة البيانات فان المعالجات تلك كانت تقوم على عنونة بايتن فقط (كل بايت = 8 بت فاذن 2 بايت = 16بت).
مسالة عنونة 2 بايت فقط تعني انه لنقل سلسلة من المحارف من مكان لاخر فان المعالج كان يحتاج الى عدد دورات اكبر, لناخذ المثال التالي مثلا.. نلاحظ كيف انه مع تطور المعالج اخذت الدورات تقل (واحيانا تزيد في بعض العمليات وفقا لتركيب المعالج نفسه)​


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

لذا مع ظهور 32بت ومؤخرا 64بت اصبح بامكان مبرمجي الاسمبلي تنفس الصعداء لانه صار بالامكان لهم نقل البيانات بصورة اسهل.. فما بالك بنقل 8بايتات مرة واحدة مع 64بت كانت تحتاج من قبل الى 4 دورات لحلقة ما مع 16بت او 2 مع 32بت!

من الاختلافات ايضا هو ان تطبيقات 16بت تكون محصورة بنظام DOS اي انها سوف تقوم باستخدام المقاطعات البرمجية Interrupts ليتم تنفيذها, في حين تطبيقات 32بت و 64بت سوف تكون ذات طابع مرئي GUI اي انها ستحوي على نوافذ ورسائل حوار ويتم استخدام الدوال البرمجية API الامر الذي يسهل حياة المبرمج

الاختلاف الاخر هو في كيفية تنفيذ الاوامر ومدى اختلاف التعليمات.. نظريا لن تجد اختلاف كبير في التعليمات بين 16 او 32بت, تم اضافة القليل من التعليمات التي قد لا تستخدمها بشكل اعتيادي.. اما فيما يتعلق بـ 64بت فهناك العديد من الاختلافات الجوهرية التي تجعل مسالة الانتقال اليه مسالة تحتاج الى تعامل جيد مع ما سبقه من لغات لتكون الاختلافات قليلة وصريحة.

هذا هو مفهوم 16, 32 او 64بت

- البرمجيات المستخدمة في كتابة تطبيقات الاسمبلي:
- الان ناتي الى البرمجيات المستخدمة لكتابة تطبيقات الاسمبلي, وهي برنامج واحد يسمى "مجمع" Assembler, هذا المجمع يقسم داخليا الى تطبيقين, Assembler + Linker - وقد تم شرح دورة حياة برنامج الاسمبلي من قبل في مقال باسم "عملية التجميع وتنفيذ البرنامج" في سلسلة الاسمبلي التي يمكن ايجادها في الارشيف.

فيما يخص الاسمبلر فالشائع استخدامه هو Masm, لكن هناك مجمعات اخرى رائدة مثل Nasm, Tasm, Goasm, الخ والتي تمتلك كل منها ميزات وحسنات من الصعب علي ذكرها لعدم استخدامي جميعها.

ايضا هناك برمجيات مخصصة لاضفاء بعض الحيوية على المجمعات + تزويد المبرمج ببعض الامور المتقدمة التي بامكانه الاستفاده منها في كتابة تطبيقه كتزويده بمحرر للملفات Resource اضافة الى قوائم واشرطة مرئية تحوي على تطبيقات فردية مساعدة (هنا بالطبع نتكلم عن التطبيقات المرئية)

يجدر الاشارة هنا الى ان Masm شائع الاستخدام على Windows وهو يعمل عليه فقط, بينما Nasm شائع الاستخدام على Linux وهو قادر على العمل على Windows ايضا

للحصول على كلا المجمعين يمكن التوجه الى صفحات موقعهم الخاص:
Masm32 (الرقم يعني انه مخصص لـ 32بت):


- أسئلة شائعة:


ناتي الان الى بعض الاسئلة الشائعة الانتشار فيما يخص الاسمبلي,
حيث يسأل الكثيرون انا محتار ماذا استخدم, masm او nasm فبم تنصحوني, نقول للسائل, اخي الكريم, كلا المجمعين يتعامل مع الاسمبلي دون اي اختلاف لكن الفرق في النهاية يكون في شكل الاستخدام حيث هناك فرق طفيف احيانا في التصريحات وبعض الامور الثانوية, بينما تجد مسالة استخدام التعليمات نفسها.. لذا انت عزيزي قادر على قراءة كلا الشفرتين بدون اي مشكلة والانتقال بينهما بدون اي معوقات.

اذن الامر في النهاية يتعلق باي نظام تريد الكتابة له, ان لم تكن تريد الكتابة للينوكس على الاطلاق فعليك بـ Masm حيث يتم تطويره كل فترة لا باس بها ولديه بعض الميزات التي تزيد عن سواه (الاراء متضاربة في النهاية والامر يعود لك)
اما لو اردت ان تكتب تطبيقات ايضا للنوكس فربما يكون من الافضل لك ان تبدا بـ Nasm كي لا يكون هناك اي فرق لديك في الاستخدام سواء على Windows او Linux وفي النهاية الفرق بين النظامين يتبع الـ syntax الخاصة باستخدام التعليمات فقط.

ايضا يسال البعض هل ابدا 16بت ام 32بت ام ماذا..
نقول له, لو سالتنا لكانت اجابتنا ابدأ بـ 16 لتتقن التعليمات على الاقل ولتشكل فكرة واضحة عن كيفية عمل تطبيقات 16بت فقط لا غير, ثم يكون بامكانك الانتقال فورا الى 32بت دون اي جهد يذكر حيث سيغدو من المتوجب عليك دراسة دوال Windows API المشتركة بين اللغات البرمجية جميعا فلا تعتقد انه لو تركت الاسمبلي فلن تحتاجها في C او فيجوال مثلا! (اللهم الا في .NET التي لم تعد تضع API في الواجهة وانما تترك لبيئتها الداخلية الاهتمام بمسالة تشكيل الملف وتنفيذه لاحقا).

البعض ايضا يقول بانه يريد تعلم الاسمبلي كي يغدو قادرا على تنقيح البرامج و/او كتابة ****************l codes للثغرات وما الى هذا, حسنا الاسمبلي هي الاساس في هذا وبدونها فلن تستطيع ان تفعل ايا مما ذكر, لكن يعود الامر في النهاية الى من يريد ان يتعلم, فلو كان غرضك فقط تنقيح وقرصنة التطبيقات او اكتشاف وكتابة ثغرات فهذا ليس باسمبلي صرف وانما سوف تحتاج الى فهم تعليمات الاسمبلي فقط ولن تضطر الى التعمق في بنيتها وكيفية كتابة التطبيقات بها.

البعض يريد ان يعرف كيف بامكانه استخدام المنقح, تم وضع رابط لمقالات تم تجميعها تشرح استخدام برنامج Olly debugger (باللغة الانكليزية) في الارشيف يمكن الوصول اليه بسهولة..


فيما يتعلق بانواع البيانات في الاسمبلي فقد تم التكلم عنها لاحقا, وذكرنا بانه هناك عدة طرق للتصريح عن انواع مختلفة من البيانات من انواع مثل int, long, double, float, string, ... تذكر فقط ما درسته كاساسيات في لغات اخرى, بان long مثلا مجاله من كذا الى كذا (-9,223,372,036,854,775,808 الى 9,223,372,036,854,775,807) لذا تلاحظ انها تحتاج الى تصريح عن متحول بحجم 4 كلمات (اي 2 dword) وهذا يمكن انجازه بالشكل:

كود:

كود:
[FONT=Traditional Arabic][SIZE=4]data    dd 2 dup (0)[/SIZE][/FONT][SIZE=4]
[/SIZE]


هنا تم التصريح عن متحول باسم data بحجم 2 dwords وتم اعتبار محتواه صفر (بالتالي سيدخل في مقطع البيانات الثابتة المصرح عنها سلفا data)

-ح مدى التشابه الكبير والسهولة في بناء عمليات التحكم في سير البرنامج Code flow, مثل هذه العمليات معروفة في لغات برمجة أخرى مثل الجملة الشرطية (IF Clause), الجمل التكرارية والحلقات لدينا: (For .. Next) و (While .. Loop) ولدينا جملة الاختيار (SWICH) وفق شروط معينة ابتدائية.

من اجل هذا سوف استخدم Masm لوضوحه واترك عمليه التحويل للمجمعات الاخرى التي تستخدمونها لكم.



- العبارة الشرطية IF Clause:

كود:

كود:
[SIZE=4]
[/SIZE]      [FONT=Traditional Arabic][SIZE=4]IF (condition) {    (statement) }[/SIZE][/FONT][SIZE=4]
[/SIZE]


وشكل اعقد:

كود:

كود:
[SIZE=4]
[/SIZE]      [FONT=Traditional Arabic][SIZE=4]IF (condition) {   (statement1) } ELSE {   (statement2) }[/SIZE][/FONT][SIZE=4]
[/SIZE]

والشكل الاخير منها:

كود:

كود:
[FONT=Traditional Arabic][SIZE=4]IF (condition1) {     (statement1) } ELSEIF (condition2) {    (statement2) } ELSEIF  (condition3) {    (statement3) } ELSE {    (statement4) }[/SIZE][/FONT][SIZE=4]
[/SIZE]


فيما يتعلق بالشكل الاول منها فكما هو واضح, العبارة مسؤولة عن التحقق من شرط معين, فلو تحقق لتم تنفيذ الكتلة statement والا لتم تخطي العبارة الشرطية ليتم متابعة تنفيذ ما يليها.

الشكل الثاني يملك كتلتين, statement1 و statement2 والذي يتعلق اختيار احداهما بالشرط, فلو تحقق الشرط condition للعبارة تم تنفيذ اول كتلة statement1 فيما عدا هذا يتم تنفيذ الكتلة الثانية statement2.

الشكل الثالث يتضمن عدة شروط ضمن عبارة واحدة, حيث نلاحظ امكانية استخدام عدة تحقيقات ضمن كتلة واحدة فلو تحقق اول شرط condition1 لتم تنفيذ اول كتلة statement1, ولو لم يتحقق تم نقل التنفيذ الى الشرط الثاني condition2 فلو تحقق لتم تنفيذ الكتلة statement2, ولو لم يتحقق لتم نقل التنفيذ الى condition3 فلو تحقق لتم تنفيذ الكتلة statement3, فيما عدا هذا يتم تنفيذ الكتلة statement4 والتي تؤخذ هنا افتراضيا لو كانت الشروط الثلاثة غير محققة.

من الجدير بالذكر انه بالامكان ايضا الاستغناء عن ELSE في الشكل الاخير لجعل العبارة تتحقق من عدة شروط معينة فلو لم يتحقق اي منها تم متابعة التنفيذ بشكل طبيعي بعد تخطي جميل الكتل statement(x).

لكننا في قسم الاسمبلي اليس كذلك؟ لذا دعونا نطلع على الشكل الذي تصبح عليه كل عبارة شرطية ضمن Masm (تنسيق غير قياسي):​

كود:

كود:
[FONT=Traditional Arabic][SIZE=4]; الشكل الأول .IF (condition)      (statement) .ENDIF  ; الشكل الثاني .IF (condition)    (statement1)  .ELSE    (statement2) .ENDIF  ; الشكل الثالث .IF (condition1)      (statement1) .ELSEIF (condition2)         (statement2) .ELSEIF  (condition3)         (statement3) .ELSE     (statement4) .ENDIF[/SIZE][/FONT][SIZE=4]
[/SIZE]


من الجدير بالذكر ايضا انه بالامكان استخدام كتل شرطية متداخلة Nested, كالشكل التالي مثلا (تنسيق Masm غير القياسي):

كود:

كود:
[FONT=Traditional Arabic][SIZE=4]if (condition-x1)     .if  (condition-y1)         (statement-y1)     .else         (statement-y2)      .endif .elseif (condition-x2)     .if (condition-z1)          (statement-z1)     .endif .endif[/SIZE][/FONT][SIZE=4]
[/SIZE]



لاحظ كيف ان اللغة (الاسمبلي) ليست case sensitive اي ليست حساسة لحالة الاحرف حيث قمت باستخدام "if" بدلا من "IF", اللهم فيما عدا تصريحات البيانات, فلا يجوز استخدام "data" و "Data" او "datA" للتصريح عن متحولات مختلفة.

ايضا لاحظ اني اهملت بالفعل استخدام ELSE للعبارة الشرطية الرئيسية.​


- قياسي.. غير قياسي.. huh؟


قد يخطر سؤال هنا, ماذا اعني بـ "تنسيق قياسي, تنسيق غير قياسي" كما ورد اعلاه..
الاجابة على هذا السؤال بسيطة, التنسيقات القياسية هي عبارة عن الشكل الاساسي للغة بدون استخدام اي طرق مساعدة (بابسط تصور وشرح للعملية).

للتوضيح, معروف عن لغة الاسمبلي انها تتعامل مع التعليمات بشكل مثل:​

كود:

كود:
[SIZE=4]
[/SIZE]      [FONT=Traditional Arabic][SIZE=4]mov  eax, blah1 mov  ebx, blah2 sub  edx, ecx xor  ebx, ecx je   somewhere cmp  eax, 1 jne  somewhere_else ...[/SIZE][/FONT]


فما فائدة CMP اذا ان كانت هي بالاساس المستخدمة للتحقق من قيمة ما؟؟
الاجابة بسيطة, ما رايته في الشفرة اعلاه هو الشكل القياسي للغة, قمت باجراء تحقق باستخدام تعليمات اسمبلي مباشرة ولم استعمل "IF" .. لكن السؤال الاخر, لماذا, الم تكن لتكن اوضح لو استعملت "IF"؟
حسنا لا اريد التعقيد لذا ساوضح الموضوع بفرعين, في البداية "IF" والاشكال الاخرى التي سنتحدث عنها ليست تعليمات اسمبلي مباشرة, بل هي

عبارة عن وظائف مكتوبة سلفا ضمن Masm تسمح للمجمع ان يقوم باستبدالها بالشكل القياسي من اللغة عند عملية التجميع.
لماذا لا نستخدمها دوما؟ لانها تحجز عدد اكبر من البايتات مما يؤدي الى زيادة حجم الملف اكثر مما لو تم استخدام التعليمات القياسية.


- اذن متى نستخدمها؟


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

- ما هو الشكل القياسي المماثل لكل عملية شرطية اعلاه؟


بالترتيب:​


كود:

كود:
[FONT=Traditional Arabic][SIZE=4]; IF (condition) {(statement)} cmp  dst, src; (condition) jne  @F ...  ..    ; (statement) ...  .. @@:[/SIZE][/FONT][SIZE=4]
[/SIZE]


كود:


كود:
[SIZE=4]
[/SIZE]      [FONT=Traditional Arabic][SIZE=4]; IF (condition)  {(statement1)} ELSE {(statement2)} cmp  dst, src; (condition) jne  @s2    ; not equal, goto (statement2) ...  ..    ; (statement1) ...  .. jmp   @F    ; exit the clause when done s2:        ; (statement2) ...  .. ...   .. @@:[/SIZE][/FONT][SIZE=4]
[/SIZE]      [FONT=Traditional Arabic][SIZE=4]
كود:[/SIZE][/FONT][SIZE=4]
[/SIZE]      [FONT=Traditional Arabic][SIZE=4]; IF (condition1)  {(statement1)} ELSEIF (condition2) {(statement2)} ELSE {(statement3)}  cmp  dst1, src1; (condition1) jne  @s2      ; not equal, goto  (statement2) ...  ..       ; (statement1) ...  .. jmp  @exit    ; exit  when done @s2:          ; (statement2) cmp  dst2, src2; (condition2) jne   @s3      ; not equal, goto (statement3) ...  .. ...  .. jmp  @exit    ;  exit when done @s3:          ; (statement3) ...  .. ...  .. @exit:[/SIZE][/FONT][SIZE=4]
[/SIZE]

لا تخف, معظم ما رايته فوق تعليقات للتوضيح اما التعليمات الاساسية فهي سطرين او ثلاثة تزيد حسب تعقيد عمليات المقارنة لديك.


- هل لي برؤية مثال ما؟

sure thing

في المثال التالي سنقوم بتغيير نص الرسالة التي سيتم توجيهها للمستخدم وفقا لمجموعة معينة من الشروط تحدد الرسالة:

كود:

كود:
[FONT=Traditional Arabic][SIZE=4]data msg1     db     "This is  our first msg, EAX = 1",0 msg2     db     "This is our second msg, EAX  != 6",0 msg3     db     "This is our last msg, 1 < EAX < 6,  definitly != 6 or 1",0 msg4     db     "I'm dump, I'm not really sure",0  msg5     db     "I'm cool, it's 6 for sure... isn't it? xP",0 hey       db     "hey to you",0  .code start:       push 1       pop  eax        .if (eax == 1)           invoke MessageBox, NULL, addr msg1, addr hey,  MB_OK       .elseif (eax < 6)           .if (eax != 6)                invoke MessageBox, NULL, addr msg2, addr hey, MB_OK           .elseif  (eax == 6)               invoke MessageBox, NULL, addr msg5, addr hey,  MB_OK           .else               invoke MessageBox, NULL, addr msg4,  addr hey, MB_OK           .endif       .else           invoke  MessageBox, NULL, addr msg3, addr hey, MB_OK       .endif       invoke  ExitProcess, NULL end   start[/SIZE][/FONT][SIZE=4]
[/SIZE]