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

الدرس الثانى MASM32

مغلق
بدأه neo في 13 مايو 2005 · 11 رد · 1,746 مشاهدة · في لغة Assembly لأنظمة 16, 32, 64 بت
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

+بسم الله الرحمن الرحيم

الدرس الثانى : بداية عملية مع الـMASM 32

MUSiC iN BacKGRoUnD LiNKiN PaRK – 4G10 (FoRGotTeN) ;-) / NoBoDY LiSteNiNG / PLaCe 4 My HeaD / NUMB

فى هذا الدرس سوف نقوم بأنتاج برنامج ويندوز يقوم بعملية بسطية جدا وهى كالمعتاد "hello world"

يقوم النظام بعمل تهيئة كبيرة و قوية جدا للمبرمج للعمل مع بيئة تساعدة على العمل بسرعة و بتحكم كبير و أفضل ما توفة بيئة الويندوز هو الـSystem API و التى تعطيك تحكم كامل فى البرنامج و النظام بشكل كامل و قوى و هناك عدد ضخم جدا يصعب حصرة من الدوال.

وهذه الدوال تكون مخزنة فى بعض المكتبات الموحودة فى النظام على شكر ملفات فعل سبيل المثال نجد أن الملفات تالية لها بعض الدوال كالأتى :-

GDI32.dll دجد أن هذه المكتبة موجود بها معظم دوال الخاصة بالعرض والجرافيك.

Kernl32.dll نجد أن هذا الملف يحتوى على معظم الدوال الخاصة بالتعامل مع الذاكرة و المعالجة.

User32.dll نجد أن هذه المكتبة تحتوى على معظم دوال التى تخص التعامل مع المستخدم مثل وجهات البرامج و مدخلات المستخدم و هكذا.

يوجد كم هائل من الدوال و كل ما تحتاجة هو معرفة مدخلات الدالة و مخرجاتها و كيفية الأستفادة من هذه المخرجات.

كل برامج الويندوز بلا أستثناء مربوطة بهذه المكتبات دينمكياً بمعنى أنه عند أستدعاء دالة API لا يعني هذا أن الدالة سيتم أحتوائها داخل شفرة البرنامج و لكن ما يحدث مشابه لذلك وهو أن النظام يقوم بعمل نسخة من الدالة لبرنامجك و بعد الأنتهاء منها يقوم النظام بالتخلص منها و هذه النقطة هى سبب مشاكل ويندوز و هى عدم وجود نظام أدارة ذاكرة يقوم بالحفاظ على الذاكرة بدون أهدار و أظن أن الجميع يشعر بذلك عندما يعمل على الحاسب لوقت طويل تجد أن الويندوز بدأ فى البطئ و تهنيج. نعود مرة أخرى الى موضوعنا و لكن كيف سيعرف النظام أن برنامجك يحتاج أستعمال دالة معينة حتى يتمكن النظام من أحضار هذه الدالة لبرنامجك حل بسيط جدا وهو أن المترجم يقوم بناء ما يسمى جدول الأستيراد ( Import table ) هذا الجدول يقوم النظام بقرأته و تحديد الدوال التى نسخه الى الذاكرة و بالتحديد يقوم النظام بقرأة أسماء الدوال و أسماء المكتبات التى تحويها و يقوم النظام بقرأت الدوال معرفت عنوانها داخل المكتبه عن طريق جدول موجود بها و هذا الجدول أسمه Export Table أو جدول التوريد و جدول التوريد يحتوي على أسماء الدوال و عنوانها أهم ما فى الموضوع أننا نقوم بأستدعاء الدوال بعنوانها و ليس أسمها اسماء الدوال مجرد وسيلة لتسهيل اتعامل معها.

لكل داله شكلان لأستدعائها على سبيل المثال

MessageBoxA

MessageBoxW

الشكلان يؤديان نفس الغرض و لكن هناك أختلاف جوهري و مهم جدا أن كل الدوال الملحقة بحرف A دوال تتعامل مع سلسلة حرفية ASCII بمعنى أخر لا يوجد دعم للغات أخرى أى حروف الأسكي فقط و مساحة الـحرف ASCII هى 8 بت أو حرف واحد 8 bites or 1 byte و يشمل الـASCII حروف اللغة الأنجليزية + حروف اللغة الثانية الموجودة على النظام.

الشكل اللأخر من الدوال هى الدوال الملحقة بالحرف W و هذه الدوال هى الدوال التى تتعامل مع نظام الحروفUNICODE و الـUNICODE نظام يسمح بوجود 65536 حرف و لكن الـunicode مساحاتة أكبر من الأسكي حيث أن الـUNICODE يعتمد على 16 بت أو حرفان 16 bites or 2 bytes و هذا يسمح بتعدد اللغات داخل السلسلة الحرفية بالنسبة للمبرمج ليس عليه الأهتمام بهذا الجزء لانه يتم التعامل معه و تحديد الأفضل بواسطة المترجم.

الأن سوف نعرض نموذج لبرنامج فارغ لتوضيح بعض النقاط التى سوف تساعدنا حتى نهاية الدروس:-

.386

.model flat, stdcall

.data

.code

start:

end start

يبدأ تنفيذ التعليمات مع بداية الـStart Label مباشرة فى الهيكل السابق ذكرة فى الأعلى, يتم تنفيذ التعليمات تعليمه تلو الأخرى حتى يتم العثور على تعليمات التحكم أو قفز أو كما تسمى التحكم فى تتدفق البرنامج Flow Control هذه التعليمات تغير مسار تنفيذ البرنامج.

و الن لنبدأ بداية أكثر فاعلية و عملية , عندما تحتاج الى أظهار رسالة للمستخدم يجب عليك أستخدام الدالة MessageBoxA و لكن كيف سيعرف المجمع عدد مدخلات هذه الدالة كل هذا يتم عن طريق تعريف الدالة كما هو بالشكل التالى

MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:DWORD

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

وهذا هو شكل هيكل التعريف

FunctionName PROTO [ParameterName]:DataType,[ParameterName]:DataType,...

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

Push arg1 ; the frist way to call the function

Push addr str1

Push addr str2

Push arg2

Call MessageBoxA

Invoke MessageBoxA,arg1, addr str1, addr str2, arg2 ; the secod way to call the function

الطريقة الأولى كما يرها البعض أنها غير أمنة نظرا لطبيعة الأنسان فى أن ذاكرته لن تسمح له بتذكل كل شئ لذلك أستخدامك لهذه الطريقة لابد أن يكون معك دليل الدوال  و فى حالة نسيان أحد المدخلات أضمن لك أنك لن تحصل على النتائج المطلوبة, فى الطريقة الثانية نجدة أكثر أناقة من الأولى حيث كل المدخلات فى سطر واحد بالأضافة فى حالة أستدخدامك لوجهة RADASM سوف تجد أن الـAuto Completion يعمل معك فى الشكل الثانى و يساعدك فى فهم مدخلات الدالة, نأتى للناحية العملية للموضوع فى الحالة الأولى لن يشعر المجمع بوجود خطاء و لكن سوف يحدث الخطأ بعد تجميع البرنامج و تشغيلة و ذلك أثناء أستدعاء الدالة , و لكن فى طريقة الثانية يتحقق المجمع من تتطابق تعريف الدالة و طريقة أستدعائة و فى حالة وجود خطأ سوف يتوقف و يعلمك بوجود خطأ, الميزة الحقيقية فى الطريقة الثانية فى السهولة فى مناولة المدخلات الدالةThe ease of parameter handlingو الأن لنرى مثال جديد ( مثال بجد )

.386

.model flat,stdcall

option casemap:none

include \masm32\include\windows.inc

include \masm32\include\kernel32.inc

include \masm32\include\user32.inc

includelib \masm32\lib\kernel32.lib

includelib \masm32\lib\user32.lib

.data

MsgBoxCaption db "Iczelion Tutorial No.2",0

MsgBoxText db "Win32 Assembly is Great!",0

.code

start:

invoke MessageBox, NULL, addr MsgBoxText, addr MsgBoxCaption, MB_OK

invoke ExitProcess, NULL

end start

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

و أول السطور التى زادت هذا السطر

option casemap:none

و هذا السطر معناه أنك تخبر المجمع الأخذ بعين الأعتبار حالة الحروف Case Sensitive لذلك نجد أن المتغير strTEXT يختلف تماما عن المتغير StRtext أو strText و هكذا.

include \masm32\include\windows.inc

include \masm32\include\kernel32.inc

include \masm32\include\user32.inc

هذه السطور فائدة للمجمع و المبرمج مهمه جدا لانها تريح كلا من الجهتين فهذه السطور معناها أحتواء ما بداخل هذه الملفات من دوال و متغيرات الى برنامجك و الا فأنك سوف تضطر الى تعريف الدوال التى تتعامل معها كما و ضحنا سابقا لذلك أنصح بأن تقوموا فتح هذه الملفات و روئية ما بداخلها ;-) .

includelib \masm32\lib\kernel32.lib

includelib \masm32\lib\user32.lib

هذه الملفات تحتوى على مكتابات يحتاجها المجمع لأكمال جدول الأستيراد و أكمال linking لبرنامجك, بالأضافة الى أن هذا السطر سوف يوفر الكثير من العناء و التعب للتعامل مع المربط LINKER.

و الأن هيا للعمل Lets get our hands dirty with the code  سوف نقوم بترجمة أول برنامج لنا

قم بتخزين الكود المذكور أعلاه فى ملف و قم بتسميته FiRST.asm قم بالدخول على مجلد الـMASM و أكتب الأمر التالى

ML /c /coff /cp FiRST.asm

و الأن ما معنى هذا السطر؟ هذا السطر كما نلاحظ أن هذا السطر مكون من 5 كلمات

الأولى ( ML ) هى أسمى برنامج المجمع الذي سوف يقوم بتجميع برنامجنا

الثانى ( /c ) معنى هذا الخيار أنك تخبر المجمع أن يقوم بعملية التجميع فقط و أنك لا تريد ربط البرنامج الأن.

الثالث ( /coff ) هذا الخيار معناه أنك تطلب من المترجم أن يقوم بأنتاج ملف هذف Object File من نوع Coff و الذي هو مخصص لنظام التشغيل يونكس وهذه الكلمة أختصار لـ(Common Object File Format ) ( نسق ملف هدف عام ).

الرابع ( /cp ) يقوم بحفظ حالة الحروف للمستخدم Case status

الخامس ( FiRST ) أسم الملف المراد تجميعة

الى هنا تكون قد أتممت عملية التجميع و لكنك لم تنتهي بعض من أنتاج ملف تنفيذي نحن الأن بحاجة الى ربط الرنامج Linking the object file

link /SUBSYSTEM:WINDOWS /LIBPATH:c:\masm32\lib FiRST.obj

هذا السطر سوف يقوم بهذه المهمة و لكن لابد أولا من فهم متغيرات البرنامج Parametars

الأول (/SUBSYSTEM:WINDOWS ) هذا السطر يخبر المترجم أنك سوف تنتج ملف لنظام التشغيل ويندوز

الثانى (/LIBPATH:<path to import library> ) هذا السطر يخبر المجمع بمسار مجلد ملفات المكتبات .

الثالث (FiRST.obj ) أسم ملف الهدف Object file.

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

أولا طريقة addr و التى أستخدمتها فى المثال السابق

Invoke MessageBox,0,addr strText,addr strCaption,0

و هذه الطريقة تقوم بأرجاع عنوان السلسة للدالة الطريقة الثانية و هى اطول فى الكود و لكنها تؤدي نفس الغرض

ثانيا طريقة LEA

LEA EDX, strText

LEA ECX, strCaption

Invoke MessageBox,0,EDX,ECX,0

تقوم الدالة LEA بتحميل عنوان المتغير فى مسجل و هى أختصار لـ(Load Effective Address)

و يمكن أيضا أستعداء الدالة بهذه الطريقة

LEA EDX, strText

LEA ECX, strCaption

Push 0

Push EDX

Push ECX

Push 0

Call MessageBox

النقطة الثانية التى كنت بصدد التدث عنها هى كيفية أستعمال الـRADASM فى تطبيق هذا المثال و الأن لنقوم بهذا المثال مع RADASM

المثال ملحق بالصور فى الملف الملحق

2nd ASM.rar

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

#2
الدرس الأول

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

#3

تشكر اخي العزيز

LEA EDX, strText

LEA ECX, strCaption

Invoke MessageBox,0,EDX,ECX,0

طريقة جميلة ....

hackerman5.jpg
#4

للعلم الطريقة التى تكون نهتئية و موجودة فعليا فى الملف التنفيذي ( موضحة فى الملف المرفق )

LEA EDX,strText
LEA ECX,strCaption

push 0
push EDX
push ECX
push 0
;Call [LibraryName.FunctionAddress]
Call user32.MessageBoxA

هذه هى الطريقة التى تكون موجودة بالفعل فى الملف التنفيذي

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

#5

براجع الدروس بعد ما انتهي من السي :D

شكرا اخ نيوو

#6

أنا عارف أن الدروس جاية فى وقت غلط

ديه أيام أمتحانات و مفيش حد بيهتم بأي حاجة دلقوتى غير الدراسة

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

#7
neo كتب:
أنا عارف أن الدروس جاية فى وقت غلط

ديه أيام أمتحانات و مفيش حد بيهتم بأي حاجة دلقوتى غير الدراسة

انا قصدت لغه السي :lol:

#8

شكرا لك أخي neo و إن شاء الله سأكون معاك في الدروس القادمة

#9

مشكور و أتوقع القراءة قريبااااااااا

==================================

#10

I see its more difficult to learn MASM32

TASM16 is easier ! :s

==================================

#11

هذا أسهل من TASM 16

لان هذا يعتمد على 32 بت بالأضافة الى أمكانيات كثيرة و دوال API

Nothing to mention except that I am Muslim

Using your brain is not bad as you think

My Blog

logo.jpg

#12

example may help

thanks for the lessons anyway

==================================

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

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