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

سلسلة تعلم الأسمبلر

مغلقرائج
بدأه chik في 12 ديسمبر 2003 · 67 رد · 23,290 مشاهدة · في المواضيع المميزة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم,

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

سنستعمل كما سبق الدكر Masm لبناء برامجنا وسأرفق الملفات اللازمة لدلك للدين لا يتوفروا عليها.

وعند برمجة الدوس فلا مفر لنا من استعمال Interruptions وخاصة الرقم 21 هيكس. ويمكن أن نعتبر Interruption كواجهة تمكننا من التواصل مع نضام التشغيل وأضن أن الكل حصل على هده النسخة المرفقة في أدوات الأسمبلر.

في بداية البداية سنتعلم طريقة كتابة برنامج ما وكيف نبني برنامجنا لنحصل على ملف exe .

على العموم هيكل أي برنامج سيكون كما يلي :

.MODEL SMALL

.data

نعلن هنا عن المعطيات ومختلف المتغيرات

وهناك نوع آخر من الداتا نتكلم عنه مستقبلا

.code

هنا بداية الكود

Start :

هنا سيبدأ البرنامج أو ما يسمى بنقطة البداية للبرنامج

وهدا نعتبره مثل main في برامج س أو س++

end Start

ننهي حلقة Start وللدكر لسنا ملزمين بتسميتها Start

يمكن أن نسميها أي شيء ولكن يجب أن يكون الإسم الأول والثاني متشابهان

End

هنا نعلن عن نهاية البرنامج

هدا سيكون الهيكل الأساسي لمعضم برامجنا ولا نزيد فيه إلا الكود الخاص ببرنامج ما.

والآن كيف نبني البرنامج.

سنستعمل Notepad لكتابة برنامجنا ونسجله على شكل ملف asm. ونضعه في مجلد يحنوي على الملفات اللازمة لدلك والمرفقة هنا أو أي طريقة أخرى تمكننا من إجراء العملية التالية في نافدة دوس:

ml test.asm

ml ضمن الملفات المرفقة فهو سيعمل Compile و Link للبرنامج في آن واحد أو يمكن أن نستعمل :

Masm test.exe

هدا سيخلق لنا ملف TEST.OBJ

ونقوم من بعد ب link test.obj ليعطينا البرنامج الأخير.

هدا طبعا إدا لم تكن هناك أخطاء ونفترض أننا سمينا ملفنا test.asm

أضن أن الكل اطلع على بعض القراءات ولا أريد أن أرجع إلى الإعادة إلا إدا كانت هناك أسئلة ما وكملخص أقول :

في الأسمبلر سنتعامل مع مختلف الرجسترات وهي من نوع 32 بايت لكن في الدوس سنستعمل إلا جزء 16 أو 8 بايت منها لأن الدوس يعمل على 16 بايت ونعلن أن داكرة الدوس مقسمة إلى segments و offsets وكدلك الرجسترات منها ما يدل على segments مثل :

CS Code Segment

DS Data Segment

SS Stack Segment

والرجسترات الأخرى مثل ax bx وغيرها وهده من نوع 16 بايت وكل واحد يمكن تقسيمه إلى جزءين من نوع 8 بايت.مثلا يمكن أن نقسم ax إلى ah و al وكلاهما من 8 بايت .al سيدل على الثمانية بايت الأولى من 0 إلى 7 والآخر ما تبقى من الثمانية الباقين.وأنصح أن نقرا عن هدا فكثيرا من المناهج تتكلم عنها وإدا كان فيه سؤال نطرحه هنا.

ولكي لا نطول الكلام وندخل التطبيق سنبدأ بأول برنامج وهدا لا يفعل شيء فبمجرد أن يبدأ سينتهي وهدا سيعلمنا كيف نخرج من برنامجنا وهو مهم جدا مع العلم أن Masm فيه ماكويات تعمل هدا ولكن نفضل أن ننجزها بأنفسنا على الأقل في الأول حتى نتعلمها.

وهنا ستبدأ اهمية لائحة Interruption وإدا اطلعنا عليها سنعرف أنه لهدا الغرض يمكن أن نستعمل Interruption 21 هيكس والدالة 4c هيكس دائما وعلما أن كل Interruption لها خصائصها فكل واحدة تتطلب Parameters مختلفة حسب العمل التي ستقوم به وتعطينا نتائج مختافة ودلك دائما حسب مهمتها. زكل هده المعطيات تكون في الرجسترات والنتائج أيضا وكما تختلف أنواع الرجسترات المستعملة حسب رقم Interruption والدالة المستعملة وكل هده المعطيات موجودة في اللائحة أو في أي منهج ل Interruptions.

وفيما يتعلق بانتهاء البرنامج قلنا سنستعمل الدالة 4c وهي لا تتطلب أشياء كثيرة فقط أن نضع رقم الدالة في ah register وبعد هدا نستدعي interruption رقم 21.

وهنا سنستعمل أول تعليمة في الأسمبلر وهي تعليمة mov وهي لها استعمالات مختلفة وتكتب كما يلي:

Mov x,y وما تقوم به هي وضع y في x فقد تكون x أو y رجسترات أم معطيات أو غير دلك وسنتطرق إلى مختلف الإستعمالات حين نستعملها.وفي مثالنا نريد أن نضع القيمة 4c هيكس في ah لدى سنقوم بما يلي:

Mov ah,4ch وهنا زدنا h في آخر 4c لنقول للكمبايلر أن الرقم هو بالهيكس.

وبعد هده التعليمة ستصبح قيمة ah هي 4c .وبعد هدا نستدعي Interruption رقم 21 هيكس ولهدا الغرض نستعمل التعليمة التالية :

Int 21h يجب وضع h ضروري فلو نسيناها سيتم استدعاء 21 عشاري وهدا قد يعطينا أي شيء وربما وقف البرنامج والتعليمة int تستعل لاستدعاء أي Interruption والبرنامج الكامل سيكون كما يلي:

.MODEL SMALL

.code

Start:

**********************;
mov ah,4ch
int 21h
**********************;
end Start

End

والملاحض هنا أننا لم نكتب .data في الأول والسبب أننا لسنا محتاجين إلى معطيات وكما يمكن أن نكتب أي تعليق في البرنامج والتعليق تسبقه ; .

نبني البرنامج باستعمال ml ولا يهمنا الإندار المتعلق بالستاك الآن.وإدا تم الكل كما يرام سنحصل على برنامج exe وحين نشغله طبعا لا يفعل شيئا بالخصوص بل ستضهر النافدة السوداء للدوس تم تختفي.

وهنا سنزيد في مثالنا أننا سنكتب حرفا على الشاشة وهنا سنستعمل دائما interruption 21 ولكن هده المرة الدالة رقم 2 وحين نتطلع علينا نجد أنه يلزمها أن تكون في ah رقم الدالة وفي رجستر dl رقم الحرف الدي نريد إضهاره وهدا كما سبق سنكتبه كما يلي.

نريد أن نضهر حرف A وقيمته أسكي هي 41 هيكس إدن سنبرمج ما يلي :

Mov ah,2 في ah نضع رقم الدالة

Mov dl,41h نضع في dl رقم الحرف و Masm يمكننا من استعمال mov dl,’A’ في عوض رقم الحرف نضع الرف نفسه بين الشرطتين علما أن المبايلر سيحوله دائما إلى الرقم.

Int 21h استدعاء interruption كما سبق.

والبرنامج كله سيكون كما يلي وهنا أيضا لا نحتاج data

.MODEL SMALL

.code

Start:

;**********************
	mov ah,2
	mov dl,41h
	int 21h

;**********************
mov ah,4ch
int 21h
;**********************
end Start

End

وبالفعل نضيف الكود السابق لكي ينتهي برنامجنا نهاية مريحة.وبعد هدا نبني برنامجنا ونتمنى أن لا نكون كتبنا شيئا ما غلط.

هدا سيكون البداية وأتمنى أن أشاهد آراءكم واقتراحاتكم لأن هده الأخيرة هي التي ستدفع بهده السلسلة إلى الأمام.

تمرين:

حاولوا كتابة حرفين يكونا في بداية السطر واحد تحت الآخر وسوف نستعمل فقط ما رأيناه سابقا والمرجو من يصل إلى هدا يعطي النتيجة هنا ونناقشها.

أتمنى أن يكون هدا المقال مفهوما وفي متناول الجميع وإلى الحصة القادمة إن شاء الله.

أتمنى لكم التوفيق وإلى اللقاء.

وهده هي ملفات masm :

Masm_Files.zip

#2

جزاك الله خيرا أخي وأستاذنا chick على هذا الدرس

عندي بعض الأسئلة

أولا :أريد زيادة بعض التوضيح حول 2 التي تأتي مع int 21

ثانيا:يعني عند الطباعة نكتب التعليمة التالية:

mov ah,2

نضع هنا القيمة أو الحرف المراد طباعت,mov dl

int 21h

والتي تعني ()write في البسكال أو هناك أوامر أخرى

ملاحظة:

الملف لا يعمل

أما بخصوص التمرين لقد إستطعت طباعة الحرفين في نفس السطر

وسأحاول لكي أطبع كل واحدة في سطر لأني دخت معها

#3

السلام عليكم,

أشكر الأخ hatem على الإهتمام بهدا الموضوع ورده السريع.

فيما يخص الرقم 2 في السطر mov ah,2 أريد أن أقول أنه لو تتصفع ملف مختلف Interruptions ستتضح لك الأمور.

نعرف أنه فيما يخص DOS فإن Interruption رقم 21 هي التي تقوم بأغلبية الشغل تقريبا وهده مقسمة إلى دوال كل دالة تفعل شيء وكل دالة تحمل رقما معينا .فالدالة المكلفة بكتابة حرف هي التي تحمل رقم 2 وهدا هو معنى هدا الرقم.

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

إلى اللقاء.

#4

السلام عليكم

لقد حاولت مرارا في أن أجد الحل ولكن هذا ما توصلت إليه

.MODEL SMALL

.code

Start:

;**********************

mov ah,2

mov dl,41h

int 21h

;**********************

mov ah,2

mov dl,20h

int 21h

;**********************

mov ah,2

mov dl,41h

int 21h

;**********************

mov ah,4ch

int 21h

;**********************

end Start

End

حيث إستطعت فصل الملفين بمسافة والتي تأخذ القيمة 20 بالهيكس وأعلم أن d هي للمفتاح enter أي للكتابة في سطر جديد ولكنها لم تعمل المهم سأحاول مرة ثانية لأني أعلم بأني إقتربت من الحال

#5

السلام عليكم أخى chik , أما بعد

مجهود طيب و ربنا يعينك على إكمال المسيره بإذن الله .

كان عندى إستفسار بخصوص تعليمات INT السابقه و هو :

- هل يجب وجود نظام تشغيل ( dos ) لتنفيذ هذه التعليمات ... لاحظ أن هذا Interupt ينادى على الداله رقم 21 فى جدول دوال النظام و الذى يقوم بتحميله نظام التشغيل عند بدأ العمل .

- أعنى هل هناك طرق أخرى فى طباعة حرف ما على الشاشه بدون إستخدام أى دوال التابعه لنظام dos ( ممكن دوال البيوس BIOS ) ؟؟؟

- أحب أن تناقشنى بهذا الموضوع....... منتظر رأيك ......

#6

السلام عليكم,

فيما يخص الأخ hatem أريد أن أقول لك أنك على الطريق السليم ويمكنك فقط تغيير الرقم 20 هكس الدي يدل على رقم فراغ space بالرقم الخاص ب return .واسمح لي فداكرتي للأرقام ضعيفة وليست معي الملفات لدلك وأضن أنه الرقم 10 أو 13 عشاري ويمكنك التأكد من هدا في لائحة الأسكي.

ويمكنك أيضا باستعمال هدا أن تقوم بسمع رنين beep إدا اخترت رقمه المناسب. وعلى العموم الطريقة هي والأرقام نغيرها حسب الضرورة.

فيما يخص الأخ mezzuz هو بالفعل نحن في أمثلتنا استعملنا دوال DOS وفيما يخص كتابة شيء من طرف BIOS فهدا أمر أكيد.

فلنفكر قليلا إن DOS سيحمل بعد قراءته على القرص الصلب أو أي قرص آخر فمثلا حين نشغل الكمبيوتر في البداية ف DOS يكون لازال لم يشتغل وهنا يمكن أن نتساءل من المسؤول عن هدا العمل . فهو بالطبع BIOS ونرى أنه يمكنه من الكتابة على الشاشة وقراءة الأقراص الصلبة وغيرها.

وحين نتصفح أي لائحة ل Interruptions فلكل واحدة منها ندكر إن كانت هده تخص DOS أو BIOS أو في أنضمة أخرى.

والخاصة ب BIOS للكتابة أضن أنها الرقم 10 ولكن يجب التأكد من هدا الرقم.

ولنفترض أنك تريد كتابة Code وتجعله على القرص الصلب ليبتدء به الكمبيوتر Startup Disk وبما أنك هنا لن يكون عندك أي نضام للتشغيل فبرنامجك يجب أن يحتوي فقط على دوال BIOS .

إلى اللقاء.

#7

لقد جربت هذه الأرقام

10h

10

13

13h

ولم أفلح لعله يوجد خطأ في نص البرنامج السابق وهذا ملف ascii

ascii.zip

#8

يسعدنى أنك تجاوبت معى سريعا .

فهمت من ردك أنك تفهمت تماما ما أعنيه إذن ...

لا تنس جانب دوال البيوس من شرحك فيما بعد إن شاء الله . أوك ؟؟

وسأكون معك هنا وبالأخص فى هذه الدوال .

#9

السلام عليكم,

إلى الأخ hatem إن الأرقام 13 و 10 عشاريا لو نكتبهما في هدا التتابع فهم يقومون بالغرض.الآن ليست لدي على هدا الكمبيوتر الأدوات للبرمجة وسأعطي هدا غدا إن شاء الله ونزيد في الدرس بتعلم تعليمات إضافية.

وحسب رأيي سنحاول استعمال هده interruption في أمثلتنا القادمة .

إلى الأخ mezzuz .

فيما يخص interruptions للبيوس أقول أنها لا تختلف على مثيلاتها في الدوس .فهي لها نفس طريقة البرمجة وتكون أسهل في الدوس لأنه بعض المرات لا نحتاج إلى parameters كثيرة في الدوس بدلا من البيوس.وعلى العموم إدا كتب لهده الدروس الدوام فلا بد أن نتطرق لهدا في يوم من الأيام.

أتمنى التوفيق للجميع وإلى اللقاء.

#10

السلام عليكم,

سنزيد في هدا الدرس بعض التعليمات فيما يخص mov وكدلك تعليمات المقارنة والقفز من مكان إلى مكان آخر وسط البرنامج.

لقد رأينا في المثال السابق تعليمة mov وهده لها عدة طرق للكتابة فنحن رأيناها في أبسطها مثل : mov ah,4 ويمكن أيضا أن ننقل محتوى رجستر إلى رجستر آخر فإدا افترضنا أن ah=5 وأن dl=8 فإذا كتبنا :

Mov dl,ah فستصبح قيمة dl 5 بينما لا تتغير قيمة ah .

هنا أخدنا الرجسترات 8 بايت ولكن الكل يتطبق أيضا على الرجسترات 16 بايت.

وهنا يجب أخذ شيء من الحذر حين نمزج رجسترات 8 و 16 بايت.فقد نقع في أخطاء .فعلى سبيل المثال إذا قلت أن

Ax=1234h و dl=8 وقمت بما يلي : mov al,dl فهذا سيغير قيمة al إلى 8 وهذا أمر واضح ولكن ماذا سيقع لقيمة ax

فبما أن ax هي مكونة من ah و dl فحتما ستتغير قيمة ax في نفس الوقت.

وفي العموم رجستر ax نقصمه كالتالي: ax=ah-alففي المثال السابق ax=1234h فهذا يعني أن ah=12h بينما al=34h وإذا غيرنا al=8 لوحده فإن ax سيصبح أوتوماتيكيا ax=1208h .

وسنأخذ مثالا الآن سنكتب 3 أحرف A B C كل حرف في سطر ونكون قد وضعنا كل حرف في رجستر معلوم:

وسيكون المثال كالتالي :

;**********************

mov cl,10 نضع في رجستر cl القيمة 10 عشاري وهي في الأسكي تعني Line Feed

mov ch,'A' نضع في ch الحرف A

mov bl,'B' نضع في bl حرف B

mov bh,'C' نضع في bl حرف C

mov ah,2

mov dl,ch نضع في dl الحرف الذي نريد أن نكتبه وهنا سيكون حرف A

int 21h

mov ah,2

mov dl,cl الإعادة إلى السطر

int 21h

mov ah,2

mov dl,bl

int 21h

mov ah,2

mov dl,cl

int 21h

mov ah,2

mov dl,bh

int 21h

mov ah,2

mov dl,cl

int 21h

mov ah,2

mov dl,cl

int 21h

;**********************

هذا الكود نضعه طبعا في الهيكل الذي أعطيناه سابقا ولا ننسى الخروج من البرنامج.

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

وقبل أن نزيد في الدرس أريد أن أعطي دالة قد نحتاجها وهي سهلة الإستعمال.ففي كثير من الأحيان حين نشغل البرنامج بنقره مرتين تفتح لنا نافذة الدوس وينجز البرنامج وتغلق النافذة من جديد ولا يكون عندنا الوقت لمشاهدة ما حصل في الشاشة.وهنا سنزيد سطرين يمكن أن نزيدها في أي مكان في الكود وهذين السطرين سيجعلان البرنامج يتوقف وينتضر من المستعمل أن يضغط على زر ما.ولهذا الغرض سنستعمل Interruption رقم 21 دائما والدالة 7 وستكون كما يلي :

;**********************

;wait for a key from the keyboard

mov ah,7

int 21h

;***********************

وللتذكير كل ما يأتي بعد ; يعتبر كتعليق فقط.إذن يمكن أن نضيف هذين السطرين في برامجنا في النهاية مثلا ولكن قبل أن نستدعي الكود للخروج من البرنامج أو في أي مكان ما نريد اإنتضار.

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

وستبقى طرقا أخرى لإستعمال تعليمة mov وسنرجع إليها في كل مرة إن شاء الله.

لكي نتمكن من كتابة برامج تشبه شيئا ما البرامج يجب أن نتعلم كيف ننجز العمليات الرياضية وكيف نقفز وسط البرنامج.

وسأحاول البدء بأبسط الأشياء.

تعليمة inc وهي إذا أنجزناها على رجستر ما فهي ستزيد 1 إلى قيمته. ويمكن أن ننجزها على رجستر 8 أو 16 بايت.

فمثلا لو عندنا ah=4 فإذا كتبنا inc ah فإن قيمة ah ستصبح 5 ويمكن أن نكتب inc ax .وعلى العكس هناك تعليمة dec وهي تنقص 1 من قيمة الرجستر وتستعمل كالأخرى تماما وهي شبيهة ++ و – في س أو س++.

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

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

ولكن في غالب الأحيان قبل أن نقفز وسط البرنامج يجب أن يكون هناك داع لذلك يعني في الحالة الأولى أذهب إلى هذا المكان وفي حالة ثانية أذهب إلى مكان آخر.وهذا يتطلب معرفة المقارنة بين شيءين وتعليمة المقارنة هي بسيطة ويمكن أن نكتبها ب cmp أي compare وهي لإيضا لها استعمالات مختلفة إذ يمكنها أن تقارن بين رجستر أو عدد أو بين رجسترين وغير ذلك :

Cmp ah,6 نقارن قيمة الرجستر ah مع العدد 6

Cmp bl,ch نقارن بين الرجستر bl و ch .

Cmp bx,cx مقارنة بين رجسترات 16 بايت.

وهنا يجب أن أن نتكلم على رجستر flag ولكن سوف نتركه إلى وقت لاحق وسنعتبر في وقتنا هذا أنه إذا كانت المقارنة متشابهة ستكون عندنا نتيجة 0 وغير 0 في الحالة الأخرى.وهنا سنتكلم عن تعليمات القفز في هذه الحالتين وهما كما يلي :

Jz و jnz . اللأولي(jmp if Zero) jz تعني القفز في حالة إذا كانت نتيجة المقارنة 0 يعني ما قارناه كانا متشابهين أما jnz (jump if not zero) فتعني القفز في الحالة الأخرى.وهذان يعتبران conditionnal jump أو القفز حسب الحال.وهناك تعليمة للقفز بدون شرط وهي jmp فهذه ستقفز إلى المكان المحدد كيفما كانت الظروف.

وسنبدأ بكتابة هذه التعليمات على الشكل jz address أو jnz address أو jmp address .و address سيكون هو العنوان الذي سيقفز عنده البرنامج.وحين نكتب برنامجنا في masm لا نهتم بقيمة address يكفي أن نعطيها labels لذلك والكمبايلر سيحدد تلك القيمة لوحده.و label سيكون أي كتابة نكتبها في بداية السطر وتتنتهي بنقطتين.ووفي غالب الأحيان يكون شكل الكود على ما يلي:

Cmp ah,bh

Jz ZeroResult

Code if not zero

Jmp continue

: ZeroResult

code if zero

:continue

Other Code

ففي هذا الكود سنقارن الرجسترات ah و bh فإذا كانا متشابهين سنذهب إلى الكود المشار إليه بالعلامة ZeroResult وبالطبع في الحالة الأخرى سينجز الكود الذي يلي هذا وحين يصل إلى التعليمة jmp سيقفز كيفما كانت الأوضاع إلى الكود المشار إليه ب continue .

ولكي نلخص كل ما رأيناه في مثال سنكتب كود يكتب العشر أحرف الأولى ابتداءا من الحرف A .

ويمكن أن نكتبه كالتالي:

mov bl,'A' نضع في bl الحرف الأول

mov cl,0 نضع في cl العداد الذي سيحسب عدد الأحرف.سنبدء من صفر

NextLetter: هذا العنوان حين نريد كتابة حرف آخر

mov ah,2 نهيء Interruption

mov dl,bl نضع في dl الحرف الذي نريد كتابته وهو موضوع مسبقا في bl

int 21h نكتب الحرف

inc bl نزيد 1 في bl ليشير إلى الحرف اللاحق مثلا A=41h و B=42h إلى آخره

inc cl نزيد 1 في العداد

cmp cl,10 نقارن العداد مع 10

jnz NextLetter إذا كان العداد لا يساوي 10 نقفز إلى السطر NextLetter وسيبدأ الكود ب mov ah=2 إلى غير ذلك.وحين يصبح العداد يساووي 10 يستمر البرنامج إلى الكود الموالي وسنضع هنا الكود للخروج من البرنامج.

يمكن أن نستغني عن العداد أو الرجستر cl وبعد تعليمة inc bl نقارن bl مع حرف K والأسطر الأخيرة تصبح كالتالي :

Inc bl

Cmp bl,’K’

Jnz NextLetter

هذا يعطينا نفس النتيجة لأن حرف K هو الحرف رقم 11 .

لقد تعلمنا هنا بعض التعليمات وهذه فد تمكننا من كتابة بعض البرامج الصغيرة.

وكتمرين يمكن أن نطبع الأحرف 26 ابتداءا من Z إلى A .

نكتب الأحرف من A إلى Z كل حرف في سطر وننتظر حتى نضغط على زر قبل نكتب الحرف الموالي.

نكتب الأحرف من A إلى Z ولكن لا نكتب الحرف X .

أتمنى أن يفيد هذا الدرس ودائما في انتضار آرائكم واقتراحاتكم أو أي سؤال.

إلى اللقاء.

#11

لسلام عليكم

بعدة حوالي 3 ساعات أو أكثر من العمل تمكنت من حل التمارين وكان الخطأ الذي وقعت فيه هو عند كتابة حرف x صغير بينما يجب أن يكون كبير.

أظن أنني أصبحت أحس بتحسن في البرمجة في لغة الاسمبلي ويعودالفضل لى أستاذنا القدير chick جزاك الله خيرا وأرجو من الأخوة المهتمين بالموضوع إرسال حلولهم لتتم مناقشتها ولعلنا نستفيد بالطرق المختلفة التي تم بها ذلك نحن الآن ننتظر الدرس الموالي

الحل:

.MODEL SMALL

.code

Start:

mov bl,'A'; bl في الرجيستر A تخزين الحرف

good: ;label

; 5bو bl نقارن بين

cmp bl,5bh

jz stop ;X إذا كانا متساويين أي كلاهما يساوي

;ينتظرالضغط على أي مفتاح على لوحة الفاتيح

mov ah,7

int 21h

;طباعة الحروف على الشاشة

mov ah,2

mov dl,bl

int 21h

;الرجوع إلى السطر

mov ah,2

mov dl,10

int 21h

; لطباعة الحرف الموالي bl زيادة 1 في

inc bl

; x والحرف bl المقارنة بين محتوى الريجستر

cmp bl,'X'

jnz good; إذا حدث التساويlabel good القفز إلى

inc bl

jmp good; label good القفز إلى

stop: ;label

;للخروج بإرتياح من البرنامج

mov ah,4ch

int 21h

end Start

End

;**********************

#12

السلام عليكم,

أشكر الأخ hatem على اهتمامه بالموضوع وأضن أنه ربما الوحيد.

فيما يخص الحل فلمدا نقارن مرتين مع X

; 5bو bl نقارن بين

cmp bl,5bh

jz stop ;X إذا كانا متساويين أي كلاهما يساوي

هنا سيقارن مع العدد 5b وأضن أنه رقم X فحين يكون متساويا سيدهب إلى stop وهنا ينتهي البرنامج وسوف لن يطبع البقية

; x والحرف bl المقارنة بين محتوى الريجستر

cmp bl,'X'

jnz good; إذا حدث التساويlabel good القفز إلى

وهنا عندك مقارنة أخرى.

على العموم أضن أن البرنامج شغال 90% وهده محاولة جيدة ويجب أن نعرف أنه نتعلم من أخطائنا.

فيمكن أن نحل الموضوع بعدة طرق وطبعا لكل واحد طريقته.

ويمكنك مثلا تجريب ما يلي :

حين نقارن مع X إدا كانت النتيجة متساوية نزيد 1 في bl ليكون فيه الحرف الموالي ونستمر ببرنامجنا كأن شيء لم يكن.ونكتفي هنا بمقارنة واحدة مع X .

أتمنى أن يكون هناك مهتمين آخرين وإلى اللقاء.

#13

شكرا لك أستاذنا chick على التوضيح

#14

السلام عليكم,

هل هناك ما يمكن أن نناقشه في هدا الحد أم نستمر إلى أشياء أخرى.

أضن أني أطرح هدا السؤال للأخ hatem فقط .

إلى اللقاء.

#15

السلام عليكم

شكرا لك أستاذنا chick على التواصل وأنا متأسف على التأخير لأني الآن في سفر ومن حبي وإهتمامي للتعلم هذه اللغة أردت تصفح الإنترنات خارج الديار وأرجو منك إتمام هذه الدروس وبهذه الطريقة لأني أرى في ذلك هي الطريقة الجيدة لتعلم هذه اللغة جزاكم الله خيرا وأرجو منكم إتمام هذه الدروس بدون يأس وفقكم الله

#16

السلام عليكم,

سأحاول إن شاء الله رغم أن الأسئلة والإقتراحات هي التي تعطي أفكارا جديدة.

أتمنى لك سفرا ميمونا وإلى اللقاء.

#17

السلام عليكم

أخي وأستاذيchick أرجو منك إتمام الدروس لأني وجد نفسي قد بدأت أتحسن في البرمجة في لغة الأسمبلي كما أرجو من الأخ Electronic boyوالذي يريد تعلم هذه اللغة المشاركة في هذه السلسلة من الدروس كما أرجو من أستاذنا الكريم إتمام هذه السلسلة معي وإن لم تكن هناك مشاركات عسى وأن تكون مرجعا للذين يريدون تعلم هذه اللغة و إلى الذين سيلحقون متأخرا وجزاكم الله خيرا .

#18

السلام عليكم,

سأحاول في الأسبوع المقبل. وأنا الآن مسافر

إلى اللقاء.

#19

أتمنى لك سفر ممتع و أنا في إنتظار الدروس .

#20

أخي chick أرجو منك أن تتذكرني ببعض الدروس لو حتى درس كل أسبوع وجزاكم الله خيرا

#21

السلام عليكم,

كنت أفكر أن أضع الدرس هدا الأسبوع لكن بعد عودة السفر تتعرضنا بعض الأشغال التراكمية . وفي القريب إن شاء الله سنبدأ من جديد.

إلى اللقاء.

#22

السلام عليكم ,

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

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

هنا سنفترض ومنذ البداية أننا لا نبرمج برامج طويلة أي لا تتعدى 64 كيلو وهذا ليس إلا طول Segment ويعني أن برنامجنا سينحصر في Segment واحد وهكذا نتهنا من هذه المشاكل على الأقل في البداية وعلما أيضا أن في 64 كيلو يمكن عمل فيه الكثير.

في هذه البداية سوف لن نتكلم بالتدقيق على Segments وسنعطي بعض الملومات الموجزة التي تهمنا الآن ومفهومها يأتي تدريجيا وبتعمق أكثر مع التجربة.إن الذاكرة في النضام الحقيقي يمكن أن نكتبها كما يلي Segment : Offset . Segment و Offset كلاهما رجستران من 16 بايت ويمكن أن نقارنها بالساعة مثلا نكتب 1 :15 تعني الواحدة و 15 دقيقة وبعد مرور 60 دقيقة يتحول رقم الساعة إلى رقم جديد ويبتدء رقم الدقيقة بالصفر من جديد وطوله 60 دقيقة وعلما أن Offset طوله 64 كيلوبايت. فكما قلنا سابقا إن برامجنا طولها لا يتعدى 64 كيلو هذا يعني أن برنامجنا سينحصر داخل Segment واحد وسوف إذن لن نهتم بهذا الأخير. فلنفترض أن برنامجنا يحتوي على عدة Segment وسأسميها بالعربية سكمنت لأنني لا أعرف تسميتها فمثلا لتحديد المعطيات x يجب تحديد مكانها في الذاكرة وذلك بتحديد السكمنت والأوفسيت . والمعطيات y قد تكون في سكمنت آخر ولتعريفها يجب مجددا تحديد السكمنت الجديد والأوفسيت الجديد. بينما في أمثلتنا سنحدد الأوفست فقط لأن السكمنت واحد للجميع. وكما أريد أن أقول أني لا أريد أن أعطي صورة سوداء على البرامج الطويلة وأن الطريقة لمعرفة أو تحديد المعطيات في الذاكرة ليست صعبة رغم تعدد السكمنت.

لكتابة جملة على الشاشة سنستعل Interrupt رقم 21H والدالة رقم 9 والبرمجة تكون كما يلي :

mov ah,09            نعطي في ah رقم الدالة
mov ds,DataSegment   نعطي في رجستر السكمنت DS سكمنت الذاكرة التي توجد بها الجملة التي نريد إبرازها
mov dx,OffsetSegment  نعطي في الرجستر DX أوفسيت الجملة التي نريد إبرازها
int 21h    هنا نستدعي Interrupt

وهنا مثال يبرز لنا جملتين على الشاشة .الجملة الأولى اسمها Text1 والثانية Text2.

.CODE
    Text1    db  "The First Message To Show",10,13,"$"
    Text2   db  "Here is an other message N 2",10,13,"$"
start:

   mov ax,cs
        mov ds,ax

        mov dx,offset Text1
        mov ah,9
        int 21h
  
   mov ah,9	
        mov dx,offset Text2
        int 21h

;************ Terminate the prog **********************
MOV AX,4C00H
INT 21h

end start

وهنا سنتكلم شيئا على هذا المثال:

.CODE هذا يعني بداية سكمنت الكود كما في الأمثلة السابقة

Text1 db "The First Message To Show",10,13,"$"

Text2 db "Here is an other message N 2",10,13,"$"

هنا نعلن الجملتين التي نريد.والإعلان يكون كالتالي:

نعطي الإسم مثلا Text1 أو أي اسم نريد وبعده نكتب db وهي تعني Define Byte هذه ستحجز بايت في الذاكرة وبما أن كل حرف يأخذ بايت فهي ستقوم بالحساب وتحجز داكرة طولها طول الجملة وتضع كل حرف في مكانه في الذاكرة وبعدها يجب إنهاء الجملة ب $ وهذا يعني آخر الجملة وإذا أردنا أن نرجع إلى السطر نزيد الأرقام 10 و 13 والتي تعني return و Line feed .وإذا كنا لا نريد الرجوع إلى السطر لا نضيفهم.

وللعلم أيضا يمكن أن نحجز Word أو Double Word باستعمال dw أو dd .

start: هنا بداية الكود وهذا مهم ليبين للبرنامج أن الكود يبدأ هنا وأن ما سبق يعتبر معطيات أو أشياء أخرى. وفي مثالنا فهما معطيات.

mov ax,cs

mov ds,ax

هذين السطرين يلخصان ما تكلمنا عنه في البداية. قلنا لكتابة جملة ما يجب تحديدها في الذاكرة وهذا يستوجب تحديد السكمنت والأوفسيت. وقلنا أيضا أن برنامجنا سينحصر في سكمنت واحد وهو بالطبع السكمنت الموجود فيه كود البرنامج. وهذا السكمنت هو CS أو Code Segment .وبما أن المعطيات هي أيضا في نفس السكمنت وبما أن سكمنت المعطيات هو DS أو Data Segment فإذن سيكون عندنا DS=CS . وقد يخطر ببال الجميع أن يكتب لهذا الغرض mov ds,cs إلا أن هذه التعليمة غير ممكنة مباشرة ويجب استخدامها بطرق أخرى والطريقة التي اخترناها هنا هي المرور عبر ax.

Mov ax,cs نضع في ax قيمة cx وبعد هذا mov ds,ax نضع قيمة ax في ds وهو ما يعطينا في النهاية قيمة cs في ds . ويمكن أن نكتب أيضا كما يلي :

Push cs
Pop ds

وهذه التعليمات سنراها لاحقا إن شاء الله وهي تعطي نفس النتيجة كما سبق.

    mov dx,offset Text1 
        mov ah,9
        int 21h

هنا نبرمج Interrupt كما تكلمنا عنها لإبراز الجملة الأولى.

mov ah,9	
        mov dx,offset Text2
        int 21h

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

وهكذا إذن يمكن أن نكتب جملا أو رسائل نعطيها للمستعمل حسب إجراء البرنامج.

وهنا سنتكلم كيف يمكن أن ننتضر من المستعمل أن يدخل حرفا من الكيبورد ونقرا كود أسكي للحرف الذي ضغط عليه.

سنستعمل دائما Interrupt 21 والدالة رقم 1 وهي تكتب كما يلي :

mov ah,1  نعطي في ah رقم الدالة
int 21h نستدعي Interrupt

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

سنكتفي بهذا في هذه الحصة وسنرى البقية إن شاء الله في المرة القادمة علما أن هذه الأيام لدي شيء من الزكام وهو يتعب شيئا ما.

والتمرين حول ما تكلمنا عنه اليوم يمكن أن يكون كالتالي وهو قد نعبره بمثابة برنامج كامل:

في البداية نحدد كود أسكي لحرف معين مثلا نكتفي بالأسكي للأرقام من 0 إلى 9 علما أن كود أسكي لهذه هي من 30 إلى 39 بالهيكس .نطلب من المستعمل أن يدخل رقما فإذا كان أكبر من رقمنا نقول له أن عددك كبير ونطالبه بالإعادة وإذا كان صغير نقول له إن العدد صغير ونعاود وحين يحصل على الرقم نهنئه وننهي البرنامج. وكما قلت سنعمل فقط بالكود أسكي حتى نسهل البرمجة على أنفسنا .وفي هذا البرنامج سنشغل فقط ما رأيناه إلى هذه اللحضة.

أتمنى أن أرى ملاحضاتكم وآراءكم وحلولكم وأتمنى لكم التووفيق.

إلى اللقاء.

#23

السلام عليكم

شكرا لك على إتمام الدروس كما أتمنى لك الشفاء العاجل

هناك عدة أسئلة أولها أرجو أن توضح أكثر السكنمت والأوف سايد

ثانيا أظن أننا لم نرى بعد كيف يمكن كتابة علامة أكر من وأصغر من <> لأني لم أستطع كتابة البرنامج من غيرهما.

ثالثا لماذا لا يكون إستخدام الصيغة هذه mov ds,cs مباشرة

وجزاكم الله خيرا

#24

السلام عليكم,

فيما يخص السكمنت والأوفسيت فهذه تستعمل للذاكرة وهما رجستران من 16 بايت ولهذا فهي يكون طولها 65 كيلو وواحد ليس كاف ولهذا نلجأ إلى الرجستران معا وأي عنوان في الذاكرة سيحدد على شكل أوفسيت:سكمنت فحين نحدد سكمنت معين يمكن أن نتجول داخل هذا السكمنت في حدود 65 كيلو وهذا سيكون الأوفسيت.وكما قلت سابقا حين يكون برنامجنا أقل من 65 سينحصر البرنامج داخل سكمنت واحد والأوفسيت سيبتدء من 0 حتى FFFF .

نقول مثلا أننا في الذاكرة 0:0 سيكون السكمنت 0 والأوفسيت 0 يمكن مثلا أن نملأ هذه الذاكرة ب 65 كيلو بعدها ننتقل مثلا إلى 1:0 سكمنت واحد والأوفسيت مرة أخرى يمكن أن يكون من 0 إلى 65 كيلو وهكذا.

فيما يخص تعليمات أكبر أو أصغر فهناك حسب إذا كنا سنستمل الأرقام مع Sign أو لا وهذه سنتكلم عنها لاحقا وهنا يمكن أن نستعمل ما يلي jl jg jle jge.

مثلا jl تعني القفز إذا كان أصغر jle تعني أصغر أو يساوي jg تعني أكبر و jge أكبر أو يساوي .

وسنستعملها كما في المثال التالي:

cmp x,y

JL address

نقارن x مع y فإذا كان x أقل من y يقفز البرنامج إلى العنوان address .

أما السؤال الآخر فلا يمكن استعمال ذلك مباشرة لأان ليس لها تعليمة خاصة بها.

إلى اللقاء.

#25

شكرا لك أخي chick على التوضيح وهذا هو حل التمرين وأرجو أن يكون هو المطلوب

.MODEL small

.CODE

Text1 db "choose number from 0 to 9",10,13,"$"

Text2 db "your number is less than the correct number",10,13,"$"

Text3 db "your number is biger than the correct number",10,13,"$"

Text4 db "your number is true",10,13,"$"

start:

mov ax,cs

mov ds,ax

mov dx,offset Text1

mov ah,9

int 21h

mov ah,1

int 21h

cmp al,35h

jnz big

mov ah,9

mov dx,offset Text4

int 21h

jmp stop

big:

cmp al,35h

jl less

mov ah,9

mov dx,offset Text3

int 21h

jmp stop

less:

mov ah,9

mov dx,offset Text2

int 21h

stop:

;************ Terminate the prog **********************

MOV AX,4C00H

INT 21h

end start

وعندي سؤال وهو لماذا عند إدخال الرقم مباشرة ينفذ البرنامج فلو أردت مثلا مقارنته بالرقم 13 فعند كتابة الواحد ينافذ البرنامج مباشرة ولا يترك لي الفرصة في إتمام الرقم كاملا

وجزاكم الله خيرا

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

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