سوف اشرح هنا كيفية ربط MASM 6.14 مع بييئة Microsoft Visual C++ 6.0 ..
طبعا تم اختياري ل MASM 6.14 وذلك لدعمه إلى جميع تعليمات PIII و 3D-NOW و MMX ..
سوف أقوم بكتابة كود بالأسمبلي لجمع أعداد في مصفوفة ويعيد نتيحة الجمع . هذا الروتين هو في ملف منفصل امتداده ASM وعندما تقوم بترجمة مشروعك الفيجوال سي++ سوف يتم استدعاء ML.EXE ليقوم بعملية تجميع ملف ال Assembly وانتاج ملف OBJ . هذا الملف يستخدم في ال Linker تبع الفيجوال سي في ربطه مع بقية ملفات ال OBJ في مشروعك ..
العملية بسيطة جدا وشوف تتغلم أيضا كيف تنفذ روتين الأسمبلي خطوة خطوة أي Tracing .. من أجل عمليات ال Debugging ..
يجب أن يكون لديك نسخة MASM 6.14 من أجل أن تقوم بتجربة المثال التالي .
سوف أبدأ بمشروع Console Application فارغ وأقوم باضافة ملف TXT جديد (فارغ) إلى المشروع وأحفظه باسم add.asm وبالتالي تصبح شجرة المشروع كالتالي :
الآن اكتب هذا الكود في ملف الأسمبلي :
[code2]
.586P ; directive for the processor used
.model FLAT, C ; We need to use all the memory as one segment, and C style
_TEXT SEGMENT ; the code segment should be _TEXT
; Your code goes here
; adda is a public procedure which accepts two pointers
; the first parameter is DWORD (pointer 32-bit)
; the second parameter is WORD (16-bit)
adda PROC NEAR PUBLIC,
array : DWORD, count : WORD
mov esi, array ; move the address of the array to esi
xor eax, eax ; clear eax
mov cx, count ; load the count in ecx
.WHILE cx != 0 ; while (cx != 0) {
add eax, [esi] ; eax += [esi];
add esi, 4 ; esi += 4;
dec cx ; cx--;
.ENDW ; }
ret ; return eax;
adda ENDP
_TEXT ENDS
END
[/code2]
سوف أقوم بشرح البرنامج على السريع :
586P في البداية هي موجه للأسمبلر من أجل تفعيل تعليمات معالجات بنتيوم 1 .. مع تفعيل تعليمات النمط المحمي .
استخدمنا MODEL من نوع FLAT لأن هذا هو النوع الذي عليه برامج الويندوز 32bit واستخدمنا لغة التوافق هي C وهذا ضروري من أجل استخدام البارامترات في تعريف التوابع في الأسمبلي بطريقة آلية.
كما ترى الروتين تم تحيدي PUBLIC من أجل أن تراه الملفات الأخرى وتم تحديد البارامترات مباشرة .
يمكنك طبعا استخدام العديد من الMACROS في MASM وأنا هنا مستخدم WHILE وهي تولد الكود اللازم من أجلها.
طبعا يتم إعادة القيمة الموجودة في EAX إلى البرنامج الذي استدعى .
الخطوة الثانية وهي كتابة ال prototype لهذا الروتين في ملف السي الذي يريد استدعائه وهو كالتالي ..:
[code2]
extern "C" int adda(int*, short);
[/code2]
كما تلاحظ استخدامنا ل "extern "C وهي ضرورية إذا كنت تترجم في سي++ وذلك بسبب أن السي++ تستخدم أسماء مختلفة للروتينات تعتمد على أنواع البارامترات . يعني داخليا التابع adda في سي++ يتغير إلى شيئ يشبه adda@@YAHPAHF@Z وهذا الاسم يدل على نوع البارامترات . هذا سبب أن السي++ تسمح با overloading للتوابع (حيث نفس اسم التابع يمكن اعادة برمجته مع تغيير انواع البارامترات ) . الآن بما أن الأسمبلي ليسة متوافقة مع هذه التواقيع في سي++ فيجب أن نقول لسي++ أننا لا نريد توليد هذه الأمور ونريد أن يتم معاملة هذا التابع كما لو أنه مبرمج في السي . هذا سبب استخدامنا إلى "extern "C .
الخطوة التي يمكن عملها في اي وقت وهي كيفية أن تقول للفيجوال سي++ أننا نريد استخدام ML.EXE من أجل عمل تجميع لملف الأسمبلي لدينا ... هذا سهل عن طريق ما يلي :
اضعط بالزر الأيمن على ملف الأسبملي واختر Settings من القائمة . وسوف تظهر لك نافذة Project Settings ومعلم على الملف add.asm واذهب إلى الصفحة Custom Build على اليمين . كما هو موضح في الصورة :
إن Custom Build من اسمها تسمح لك بتحديد بطريقة يدوية كيف سوف يتم ترجمة الملف وهنا طبعا سوف نضع الصيغة الصحيحة من أجل استدعاء ml.exe ..
طبعا سوف تكتب صيغتين واحدة من أجل ال Release والأخرى من أجل ال Debug . يتم اختيار الRelease و الDebug من Settings For . لماذا هذا الاختلاف بين الRelease و ال Debug .. طبعا أنت تعلم أنه في نسخة ال Debug لمشروعك فإنك تستطيع أن تقوم بتنقيح البرنامج وتنفيذه خطوة حطوة ومشاهدة المتحولات . هذا ناتج لأن الفيجوال سي++ تقوم بتوليد معلومات ال debug في ملف امتداده pdb هذا الملف يحتوي على جميع المعلومات الضرورية من أجل المنقح ليعلم عن المتجولات وعلاقة لفة الآلة بكود السي++ . ومن أجل أن تستطيع أن تقوم بتنقيح ملف الأسمبلي تبعك يجب أن تخير ال ml.exe أنك تريد توليد معلومات ال debug .
برنامج ال ml.exe هو عبارة عن Command Line Assembler أي يتم تمررير الخيارات عن طريق بارامترات في الcommand line وقت تنفيذه .. يوجد العديد من البارمترات وممكن أن تحصل عليها عن طريق تنفيذ ml.exe /help ..
لنرجع إلى نافذة Project Settings .. من أجل الRelease قم بكتابة ما يلي في صندوق الcommands :
// أكتب هذا في مربع commands
f:masm614binml.exe /c /Cx /coff /Fo$(ProjDir)Release$(InputName).obj $(InputDir)$(InputName).asm
// أكتب هذا في مربع Outputs
$(ProjDir)Release$(InputName).obj
الماكروات التي تراها في النص السابق يمكن الحصول عليها بسهولة عن طريق الزرين Directory و Files ..
سوف أقوم بشرح البارامترات المستخدمة هنا وهي :
c : تعني عملية تجميع assemble من غير ربط link .. ينتج منها ملف مصدري obj فقط .
Cx : يجب أخد حالة الأحرف الصغير والكبير في التوابع العامة public .
coff : تنتج ملف obj متوافق مع بيئة الفيجوال سي++ ، وهي نوع متطور عن النوع القديم obj .
Fo : تحدد موقع ملف ال obj الناتج وهنا وضعته في دليل المشروع ومنه في دليل Release .
ومن ثم تحدد اسم الملف الذي تريد تجميعه وهو هنا في حالتنا تم تحديده عن طريق الماكروات المتاحة.
أما في مربع Outputs فمن خلاله تخير الفيجوال سي++ أين يتوضع الملف الناتج ومنه تستطيع أن تعلم متى أصبح الملف قديم من أجل ترجمته أو تجمبعه من جديد .
بالنسبة إلى ال debug فأكتب مايلي :
// أكتب هذا في مربع commands
f:masm614binml.exe /c /Cx /coff /Zd /Zi /Zm /Fo$(ProjDir)Debug$(InputName).obj $(InputDir)$(InputName).asm
// أكتب هذا في مربع Outputs
$(ProjDir)Debug$(InputName).obj
سوف أشرح هنا فقط البارامترات الاضافية :
Zd : تضيف أرقام الأسطر وكود السي الأساسي إلى ملف الobjet
Zi : تضيف أسماء المتحولات إلى ملف ال object
Zm : معلومات التنقيح متوافقة مع MASM 5.10 .. (وذلك للاحتياط)
وطبعا هنا فقط عدلنا من الدليل Release إلى Debug ..
الآن عندما تقوم بترجمة مشروعك فإن الفيجوال سي++ سوف تستدعي MASM بشكل آلي من أجل تجميع الملف وسوف تظهر نتيجة التجميع في شاشة الخرج وسوف تظهر جميع الأخطاء في شاشة الخرج output كما في الصورة التالية .. حيث قمت بافتعال كم خطأ في كود الأسمبلي :
ولاحظ عند الضغط على أي خطأ مرتين يتم الذهاب مباشرة إلى السطر الخطأ ..
الآن من أجل تجربة البرنامج والتأكد من عمله أكتب مايلي في ال main :
[code2]
extern "C" int adda(int*, short);
int main()
{
int arr[] = { 1, 2, 3 };
int sum;
sum = adda(arr, sizeof(arr)/sizeof(int));
printf("sun = %dn", sum);
return 0;
}
[/code2]
وتأكد أنك مختار Debug في Set Active Configuration في القائمة Build .. وذلك لأننا نريد تنفيذ البرنامج خطوة خطوة .. والآن قم بترجمة المشروع عن طريق الضغط على F7 ومن ثم بعد أن تتأكد من عدم وجود أخطاء قم بتنفيذ البرنامج خطوة خطوة عن طريق الضغط على F11 .. واستمر بالتنفيذ .. وإذا كانت جميع خطواتك مثل ماذكرت سابقا فيجب أن تستطيع الدخول إلى ملف الأسمبلي وتنفيذه خطوة خطوة .. ويمكنك أن تفعل نافذة مشاهدة المسجلات أو تضع watch للمتحولات المستخدمة في البرنامج تماما مثل ماتفعل في السي++ .
وهذه الشاشة توضح ذلك :
لاحظ أن يوجد عرض لمسجلات ال MMX من MM0 إلى MM7 كل واحدة بعرض 64بت ومسجلات الجديدة في PIII وهي XMM0 إلى XMM7 وكل واحدة بعرض 128 بت .. وطبعا المسجلات العادية ..
وعند تنفيذ الكود سوف تحصل على النتيجة الصحيحة ..
هناك عدة أمور يجب الانتباه عليها وهي تسمية المقاطع .. فرضا إذا أردت أن تضع DATA في برنامج الأسمبلي فيجب أن تكون في مقطع _DATA أو _BSS أو CONST .. والكود كما لاحظت في _TEXT وذلك حتى يعرف الlinker كيف يقوم بعملية الربط ..
في النهاية .. أقول أنه طبعا يمكنك استخدام ال inline assembly في الفيجوال سي++ مباشرة عن طريق استخدام الكلمة المحجوزة __asm .. وإن لم تكن تعلم فهي تدعم إلى معالج ال MMX . وهي عملية جدا .. ولكنها غير كفئ من أجل المحترفين والذين يريدون التحكم في روتين الأسمبلي بشكل كامل و ايضا هذه الطريقة عملية من أجل كتابة أو نقل الروتينات التي كتبت بشكل منفصل في ملفات أسمبلي منفصلة بحيث يتم دمجها مع مشروعك بطريقة عملية ..
المشروع موجود في الوصلة :
http://arabteam.nicmatic.com/atassi/masm2vc4.zip