ارايه دهنده : حسن عسكرزاده زبانهای ماشين و برنامه سازی سيستم اصول اساسی برنامه نويسی به زبان اسمبلی مو لف : Richard C. Detmer مترجمين : هاشمی اصل - مشحون ارايه دهنده : حسن عسكرزاده
فهرست مطالب فصل اول : نمایش داده ها در کامپیوتر فصل اول : نمایش داده ها در کامپیوتر فصل دوم : قسمت های یک سیستم کامپیوتری فصل سوم : استفاده از اسمبلر فصل چهارم : دستورالعملهای اساسی فصل پنجم : انشعاب و حلقه فصل ششم : روال ها فصل هفتم : عملیات رشته ها فصل هشتم : سایر حالت های آدرس دهی فصل نهم : دستکاری بیت ها فصل دهم : وقفه و ورودی / خروجی فصل یازدهم : پردازش اسمبلی فصل دوازدهم : ماکرو ها و اسمبلی شرطی فصل سیزدهم : مثال نمونه
نمايش داده ها در كامپيوتر فصل اول نمايش داده ها در كامپيوتر
فصل اول نمايش داده ها در کامپيوتر اعداد دودویی و شانزده شانزدهی کد های کارکتری نمایش مکمل 2 برای اعداد صحیح علامت دار جمع و تفريق اعداد مكمل 2 سيستم هاي ديگر براي نمايش اعداد
چگونگي نمايش دادهها در زبان اسمبلي: اعداد دودويي و شانزدهشانزدهي کدهاي کاراکتري نمايش مکمل 2 براي اعداد صحيح علامتدار سيستمهاي ديگر براي نمايش اعداد مکمل يک BCD مميز شناور
اعداد دودويي و شانزده شانزدهي بيت كوچكترين واحد قابل ثبت در كامپيوتر است ارزش مكاني اعداد در مبناي 2 مانند اعداد در مبناي 10 است 123 در مبناي 10 برابر است با (3*1) + (2*10) + (1*100) 1010 در مبناي 2 برابر است با (0*1)+(1*2)+(0*4)+(1*8)
نمادها در نمايش اعداد در مبناها مبناي 2 0, 1 مبناي 10 0,1,2,3,4,5,6,7,8,9 مبناي شانزده 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F A=10 ,B=11, C=12, D=13, E=14, F=15
سيستم ارزش مکاني مبناي دو: يگان دوگان چهارگان هشتگان و ... اعداد دودويي به قدري طولاني هستند که خواندن و نوشتن آنها مشکل است.
سيستم شانزدهشانزدهي ميتواند اعداد را فقط با استفاده از يک چهارم ارقام سيستم دودويي نمايش دهد. به علت تبديل ساده بين سيستم دودويي و شانزده شانزدهي، مبناي 16 بعنوان شکل کوتاه شده دودويي تلقي شود. در سيستم شانزدهشانزدهي رقمهاي 0 تا 9 مورد استفاده قرار ميگيرند؛ که علاوه بر اين، به جاي اعداد دهدهي 10 تا 15 حروف A تا F جايگزين ميگردند. سيستم ارزش مکاني مبناي شانزده: يگان شانزدهگان دويستوپنجاهوششگان و...
جدول مقايسه اعداد در مبناهاي متفاوت دودويي شانزده شانزدهي دهدهي 1 10 2 11 3 100 4 101 5 110 6 111 7 1000 8 1001 9 1010 A 1011 B 1100 C 12 1101 D 13 1110 E 14 1111 F 15
تبديل مبناي 16 به مبناي 2: يک عدد شانزدهشانزدهي ميتواند به سادگي با جايگزيني چهار بيت براي هر رقم شانزدهشانزدهي به عدد معادل دودويي تبديل شود.
تبديل مبناي 2 به مبناي 16: ابتدا از سمت راست، عدد را به دستههاي چهاربيتي تقسيم ميکنيم و سپس هر دسته را با رقم معادل شانزده شانزدهي آن جايگزين مينماييم.
روش تبديل عدد دهدهي به شانزده شانزدهي با تقسيم متوالي عدد بر 16 و قراردادن باقيمانده هادر كنار يكديگر مثال عدد 5876 در مبناي 16 به روش زير محاسبه ميشود 5876 ÷16 باقيمانده 4 376 = 367 ÷ باقيمانده 15 22 = 16 22 ÷ باقيمانده 6 1 = 16 1 ÷ باقيمانده 1 0 = 16 16F4
طول كلمات بايت 8 بيت يا 1 بايت كلمه يا WORD 16 بيت يا 2 بايت بايت 8 بيت يا 1 بايت كلمه يا WORD 16 بيت يا 2 بايت كلمه مضاعف يا double word 32 بيت يا 4 بايت در يك عدد مثبت بايد بيت منتها اليه سمت چپ صفر باشد
تبديل مبناي 2 به 10: براي تبديل يک عدد دودويي به معادل دهدهي آن، به جاي تبديل مستقيم و طولاني، سريعتر خواهد بود که آن را به مبناي 16 و سپس به مبناي 10 ببريم.
2) کدهاي کاراکتري در کامپيوتر به حروف، اعداد، علامتها و کاراکترهاي ديگر، يک عدد نسبت داده ميشود. سيستمي که به طور عمومي در ريز کامپيوترها مورد استفاده قرار گرفته است کد استاندارد امريکايي براي تبادل اطلاعات است (که به صورت مخفف ASCII (American Standard Code for Information Interchange) ناميده ميشود.)
در سيستم اسکي از هفت بيت براي نمايش دادن کاراکترها استفاده ميشود. به اين ترتيب ميتوان 128 کد مختلف اسکي را نمايش داد. کدهاي اسکي معمولاً به صورت اعداد در مبناي شانزده 00 تا 7F و دهدهي 0 تا 127 نمايش داده ميشوند.
بين کد هر حرف بزرگ و کد کوچک همان حرف، در يک بيت تفاوت وجود دارد در حروف بزرگ بيت 5، صفر است و در حروف کوچک، يک، ولي بيتهاي ديگر مشابه هستند
کاراکترهاي 0016 تا 1F16 بعنوان کدهاي کنترلي شناخته ميشوند. 0D16 و 0A16 به ترتيب کدهاي برگشت به اول سطر (CR) و خط خور (LF) هستند. در صفحه کليدهاي اسکي وقتي کليد Enter يا Return فشار داده شود کد 0D16 توليد ميگردد. وقتي اين کد به يک صفحه نمايش اسکي فرستاده شود، باعث ميشود که مکاننما به ابتداي خط جاري ( و نه خط بعدي) برود. کد 0A16 مکان نما را يک خط به طرف پائين حرکت ميدهد. در اين صورت مکاننما به ابتداي خط نخواهد رفت.
3) نمايش مکمل 2 براي اعداد صحيح علامتدار سيستم مکمل 2 يک روش خيلي خوب براي ذخيره کردن اعداد علامتدار صحيح به صورت دودويي است. وقتي يک عدد به شکل مکمل دو نشان داده ميشود، تعداد بيتهاي مورد استفاده بايد از قبل مشخص گردد. براي نمايش يک عدد صحيح مثبت به شکل مکمل دو، ابتدا بايد آن را به صورت دودويي با صفرهاي اضافي نوشت تا طول موردنظر به دست آيد.
در يک عدد مثبت بايد بيت منتهياليه سمت چپ يا با ارزشترين بيت، صفر باشد. وجود «يک» در اين بيت مشخصکننده آن است که عدد منفي است. بقيه بيتهاي عدد منفي همانند بيتهاي عدد بدون علامت متناظر آن نيست.
مکمل دو يک عدد منفي: ابتدا آن را به صورت عدد بدون علامت در مبناي شانزده بيان کرده و سپس براي نمايش آن به شکل کلمه، آن را از 100 0016 تفريق ميکنيم. و براي نمايش آن به شکل مضاعف، آن را از 100 00 00 0016 تفريق ميکنيم.
عددي که بايد عدد اصلي را از آن تفريق کرد عبارت از يک عدد يک (1) است و به دنبال آن بايد همان تعداد رقم که در عدد موجود است صفر قرار داد.
گرفتن مکمل دو يا مکمل گيري: عمل تفريق کردن عدد از يک عدد «يک» که به دنبال آن تعداد صفرهاي لازم قرار گرفتهاند، را گويند. در نمايش مکمل دو، تعداد ارقام معين است در نتيجه مشخصاً ميتوان بزرگترين عددي را که در آن قابل نمايش است، تعيين نمود. در نمايش به صورت کلمه، بزرگترين عدد مثبت 7F FF است. زيرا اين بزرگترين عدد 16 بيتي در نمايش به صورت دودويي است که با ارزشترين بيت آن صفر است. اعداد مثبت که به صورت مبناي 16 نوشته ميشوند ميتوانند در سمت چپ خود يکي از ارقام صفر تا 7 را داشته باشند.
اگر مکمل دو عددي را بگيريم و سپس از حاصل مجدداً مکمل دو بگيريم به عدد اصلي برميگرديم.
اگر عمل را بر روي يک عدد منفي آغاز کنيد، نتيجه عمل گرفتن مکمل دو به يافتن عدد بدون علامت متناظر به آن ختم خواهد شد.
جمع و تفريق اعداد مکمل دو: يک دليل استفاده از روش مکمل دو براي ذخيره کردن اعداد صحيح علامتدار آن است که عمليات جمع و تفريق ميتوانند به سادگي و به طور کارآمد در سختافزار کامپيوتر پيادهسازي شوند.
يک رقم را از باارزشترين مکان به مکان بعدي به طرف چپ انتقال ميدهد و يک رقم «اضافي» ايجاد ميکند. سختافزار کامپيوتر در زمان عمل جمع ميتواند سرريز را تشخيص دهد. کامپيوتر در واقع جمع را به صورت دودويي انجام ميدهد و بر روي جفت بيتها از سمت راست به چپ عمل ميکند.
سرريزي زماني رخ ميدهد که رقم نقلي به داخل بيت علامت با رقم نقلي از بيت علامت متفاوت باشد.
رقم نقلي به بيت علامت رقم نقلي از بيت علامت سرريزي خير بله
تفريق اعداد به صورت مکمل دو، در صورت امکان همانند تفريق اعداد بدون علامت است. اگر عدد دوم بزرگتر از عدد اول باشد، در سمت چپ عدد اول يک عدد 1 اضافه ميکنيم.
سرريزي نيز براي تفريق تعريف ميشود سرريزي نيز براي تفريق تعريف ميشود. چنانچه در يک تفريق، حاصل تفريق خارج از محدوده -32768 تا 32768 باشد مشاهده خواهد شد که سرريزي رخ ميدهد و پاسخ نادرست ايجاد ميگردد. براي تشخيص سرريزي، همانند کامپيوتر، بايد تفريق را به جمع تبديل کرد، براي اينکار لازم است مکمل عدد دوم گرفته شود و يک واحد به آن افزوده گردد. حال اگر در اين عمل جمع سرريزي رخ دهد در تفريق اصلي نيز رخ خواهد داد.
سيستمهاي ديگر براي نمايش اعداد مکمل يک دهدهي دودويي شده(BCD) مميز شناور
گرفتن مکمل يک: براي به دست آوردن عدد منفي کافيست که تمام بيتها را معکوس کنيم، تمام صفرها را به يک و تمام يکها را به صفر تبديل نماييم گاهي اوقات اين عمل، گرفتن مکمل يک ناميده ميشود.
مکمل يک داراي معايب زيادي است و عمدهترين آنها اين است که طراحي مدار براي انجام جمع يا تفريق در اين اعداد مشکلتر است و براي عدد صفر دو گونه نمايش وجود دارد. محدوده اين اعداد تا حدي کوچکتر ميشود. چنانچه مکمل يک عددي را بگيريد و يک واحد به آن بيافزائيد، مکمل دو آن عدد به دست ميآيد.
اغلب اعداد BCD با تعداد معيني بايت نشان داده ميشوند.
روش مميز شناور، اعداد را به شکل نزديک به نماد علمي ذخيره ميکند. توان دو، دقيقاً همانند نمايش علمي در سيستم دهدهي است که در آن توان، با شمردن تعداد ارقامي که مميز بايد به سمت چپ يا راست حرکت کند تا مانتيس موردنظر به دست آيد، حاصل ميشود.
به طور خلاصه، ميتوان مراحل زير را براي تبديل يک عدد دهدهي به فرم ساده IEEE بيان داشت: آخرين بيت سمت چپ در اين نوع نمايش در اعداد مثبت صفر و در اعداد منفي يک است. عدد را به صورت بدون علامت در سيستم دودويي بنويسيد. عدد را به شکل نماد علمي دودويي بنويسيد که در آن f23=1 است. 24 بيت کسري وجود دارد اما نياز نيست که صفرهاي اضافي سمت راست نوشته شوند. عدد ثابت 12710 را به عدد نما يعني e اضافه کنيد. اين مجموع در فرم دودويي در هشت بيت بعدي جواب است که به دنبال بيت علامت قرار ميگيرد. بيت کسر آخرين 23 بيت عدد با مميز شناور را تشکيل ميدهند. بيت f23 حذف ميگردد.
کامپيوتر عمليات رياضي بر روي اعداد با مميز شناور را معمولاً کندتر از عمليات بر روي اعداد مکمل دو انجام ميدهد. البته مزيت قبول کردن اعداد غيرصحيح يا اعداد خيلي بزرگ يا خيلي کوچک اين عدم کارآيي نسبي محاسبات با آنها را به کنار ميزند.
تمام دادهها در کامپيوتر با استفاده از سيگنالهاي الکترونيکي نمايش داده ميشوند. اين سيگنالها ميتوانند به صورت الگوهايي از ارقام دودويي (بيت) تفسير گردند. اعداد ميتوانند به صورت دهدهي، شانزده شانزدهي يا دودويي نوشته شوند. در اعداد مکمل دو، جمع و تفريق ساده است. زيرا طول يک عدد مکمل دو محدود است و امکان رقم نقلي و غيره وجود دارد.
قسمتهاي يك سيستم كامپيوتري فصل دوم قسمتهاي يك سيستم كامپيوتري
مطالب اين فصل سخت افزار pc نرم افزار pc حافظه اصلي واحد پردازش مركزي دستگاههاي ورودي / خروجي نرم افزار pc سيستم عامل ويرايشگر متن مترجم زبان و پيوند دهنده برنامه
واحد پردازش مركزي
سختافزار PC: حافظه اصلي يک کامپيوتر حقيقي شامل سختافزار و نرمافزار ميباشد. اجزاء اصلي سختافزاري يک سيستم ريزکامپيوتر معمولي عبارتند از: يک تراشه واحد پردازش مرکزي (CPU) تراشههاي حافظه يک صفحه کليد براي ورودي يک مانيتور براي نمايش خروجي يک يا چند گرداننده ديسک براي ذخيرهکردن برنامهها و دادهها.
نرمافزار به برنامههايي که سختافزار اجرا ميکند، اطلاق مي شود. حافظه اصلي يک مجموعه منطقي از مکانهايي است که هرکدام ميتواند يک بايت دستورالعملها يا دادهها را ذخيره نمايد. هر بايت حافظه اصلي داراي يک برچسب عددي به نام آدرس ميباشد.
تصوير منطقي حافظه اصلي pc ... 00000 00001 9FFFD 9FFFE FFFFE FFFFF تصوير منطقي حافظه اصلي pc
حافظه اصلي يک PC در حقيقت متشکل از مدارهاي مجتمع (IC) ميباشد. RAM: اين حافظه با دستيابي تصادفي ميباشند که ميتواند با استفاده از دستورالعملهاي برنامه، اطلاعاتي را روي آنها نوشته و يا خواند. محتواي تراشههاي RAM با قطع جريان برق کامپيوتر از بين ميرود. ROM: محتواي آنها دائمي بوده و ميتوان فقط آنها را خوانده ولي نميتوان روي آنها نوشت.
حافظة اصلي يک PC را ميتوان به صورت مجموعهاي از سگمنتها در نظر گرفت حافظة اصلي يک PC را ميتوان به صورت مجموعهاي از سگمنتها در نظر گرفت. يک سگمنت به طول 64k بايت بوده و آدرس شروع آن مضرب 16 ميباشد.
به جاي استفاده از پنج رقم شانزده شانزدهي آدرس يک بايت حافظه اصلي، ميتوان آنرا با سگمنت حاوي بايت مزبور و به دنبال ان افستي که از ابتداي سگمنت ياد شده در نظر گرفته ميشود، آدرسي دهي کرد. آفست برابر فاصله بايت مورد نظر از اولين بايت سگمنت مربوطه ميباشد.
آدرسدهي يک بايت با استفاده از سگمنت و آفست آن آفست yyy آدرس اين بايت برابر XXX0+YYYY شروع سگمنت XXXX آدرسدهي يک بايت با استفاده از سگمنت و آفست آن
چنين آدرسي به صورت چهار رقم شانزده شانزدهي سگمنت و سپس کاراکتر کولن (:) و به دنبال آن چهار رقم شانزده شانزدهي افست ذکر ميگردد.
براي بدست آوردن آدرس پنج رقمي شانزده شانزدهي، آدرس شروع و افست را با هم جمع ميکنيم. يک بايت را ميتوان با ترکيبات مختلف «افست: سگمنت» آدرس دهي کرد.
سختافزار PC: واحد پردازش مرکزي CPU تراشه 8088 داراي 14 ثبات ميباشد که هر کدام يک محل ذخيره سازي داخلي بوده و ميتواند يک کلمه 16 بيتي را نگه دارد.
ثباتهاي Ax، Bx، Cx، Dx را ثباتهاي دادهاي يا ثباتهاي همگاني ميگويند. ثبات Ax را با توجه به اينکه بسياري از نتايج محاسبات در آن قرار ميگيرند، گاهي آکومولاتور (accumulator) ميگويند.
هر کدام از ثباتهاي Ax، Bx، Cx، Dx را ميتوان به صورت دو ثبات 8 بيتي مستقل يعني نصف بالا براي 8 بيت سمت چپ و نصف پائين براي 8 بيت سمت راست، استفاده نمود. اسامي اين ثباتهاي هشت بيتي عبارتند از AH، Al، BH، CL , CH، DL , DH. در اينجا حروف H و L به ترتيب قسمتهاي بالائي و پائيني ثباتها را نشان ميدهند.
ثبات CS شامل شماره سگمنت حافظه سگمنت کد يعني ناحيهاي از حافظه اصلي که دستورالعملهاي اجرائي برنامه در آنجا ذخيره ميشوند، ميباشد.
ثبات DS شامل شماره سگمنت حافظه سگمنت دادهها ميباشد. ثبات ES شامل شماره سگمنت حافظه سگمنت فوقالعاده ميباشد. ثبات SS شامل شماره سگمنت حافظه سگمنت پشته ميباشد.
يک پشته، يک ساختار اطلاعاتي شبيه پشته سينيها در يک رستوران ميباشد. ثبات SP، اشاره گر پشته بوده و شامل افست کلمة بالائي پشته ميباشد. SP
يک کاربرد عادي پشته در فراخواني روالها ميباشد. افست دستورالعمل بعد از دستور العمل فراخواني روي پشته ذخيره ميگردد. در موقع برگشت از روال، اين افست از پشته بازيابي ميشود.
ثباتهاي SI و DI ثباتهاي انديس ميباشند. ثباتSI برابر انديس منبع (Source Index) و ثبات ID برابر انديس مقصد (Destination Index) ميباشد.
ثبات اشاره گر دستور العملها يعني IP، نميتواند بطور مستقيم توسط برنامه نويس زبان اسمبلي دستيابي شود.
ثبات نشانه: بعضي از 16 بيت اين ثبات براي نشان دادن نتيجه اجراي دستورالعمل بوسيله دستورالعملهاي مختلف تغيير پيدا ميکنند. هر کدام از اين بيتها را يک بيت وضعيت يا بيت نشانه ميگويند.
سختافزار PC: دستگاههاي ورودي/خروجي يک دستگاه ورودي/خروجي معمولاً از سه تا هشت درگاه استفاده ميکند. اين آدرسها از آدرسهاي حافظه معمولي متمايز ميباشند.
نرمافزار PC: نرم افزار به برنامهها يا روالهايي که بوسيله سخت افزار اجرا ميشوند، اطلاق ميشود. دليل لزوم سفارش سيستمعامل اينست که: سيستمعامل از يک عده روالهاي نرمافزاري استفاده ميکند که به طور دائمي روي تراشههاي ROM ذخيره ميشوند و اين روالها از يک سيستم به سيستم ديگر تغيير ميکنند.
نرمافزار PC: ويرايشگرهاي متن يک ويرايشگر متن، برنامهاي است که ميتوان به وسيله آن فايلهاي متني را روي ديسک ذخيره کرده يا آنها را تغيير داد. يک فايل متني مجموعهاي از کدهاي اسکي است. ويرايشگر EDLIN با توجه به اينکه يک فايل متني را به صورت مجموعهاي از خطوط در نظر ميگيرد، يک ويرايشگر خطي ناميده ميشود.
واژهپردازها، ويرايشگرهاي متني ميباشند که سرويسهاي اضافي براي قالببندي و چاپ مستندات ارائه ميدهند.
ميتوانيم براي آماده ساختن يک فايل کد منبع زبان اسمبلي از يک واژهپرداز استفاده کنيم، ولي يک واژهپرداز ميتواند اطلاعات قالببندي را به همراه کدهاي اسکي متن مورد نظر در داخل يک فايل ذخيره کند. چنين اطلاعات اضافي ممکن است فايل مزبور را به عنوان يک فايل کد منبع زبان اسمبلي غيرقابل استفاده گرداند.
نرمافزار PC: مترجم يک زبان و پيونددهنده برنامه مترجم يک زبان برنامهاي است که کد يک منبع را به فرمي تبديل ميکند که ميتواند توسط کامپيوتر اجرا شود. مترجمها را ميتوان به سه گروه تقسيم نمود: مفسرها کامپايلرها اسمبلرها
مفسرها: يک برنامه منبع را به طور مستقيم ترجمه ميکنند. يک مفسر براي اجراي يک برنامه، يک خط از برنامه منبع را گرفته و دستورالعملهاي واقع در خط مزبور را اجرا ميکند. برنامههايي که تفسير ميشوند معمولاً به طور نسبي کند اجرا ميشوند. به کمک يک مفسر تغيير و اجراي يک برنامه به سرعت صورت ميگيرد.
کامپايلر: يک کامپايلر يک کد منبع را گرفته و کد هدف آن را که معمولاً متشکل از دستورالعملهايي ميباشد که به وسيله CPU مورد نظر اجرا ميشوند، تشکيل ميدهد. کد هدف توليد شده به وسيله يک کامپايلر بايستي غالباً پيوند (link) داده شده و يا با کدهاي هدف ديگر ترکيب شود تا بتوان آن را به داخل حافظه اصلي بار کرده و اجرا نمود. برنامههاي کامپايل شده خيلي سريعتر از برنامههاي تفسير شده اجرا ميشوند
اسمبلر: يک اسمبلر خيلي شبيه کامپايلر ميباشد اما زبان اسمبلي را به زبان ماشين ترجمه ميکند. غالباً براي اجراي فايلهاي نتيجه، بايستي آنها را پيوند داد.
فصل سوم استفاده از اسمبلر
مطالب اين فصل دستورالعملهاي اسمبلي چگونه بايد برنامه را اسمبل لينك و اجرا كنيم فايل ليست اسمبلر عمولوند دستورات DB و DW عمولوند دستورالعملها ورودي خروجيهاي تعريف شده در IO.H
دستورالعملهاي زبان اسمبلي هر دستورالعمل زبان اسمبلي در روي يک خط فايل کد منبع وارد ميشود. يک خط ميتواند حداکثر 128 کاراکتر داشته باشد. وجود خطوط خالي مجاز است و استفاده از آنها براي جدا کردن بخش هاي مختلف کد برنامه مفيد است.
توضيحات براي مستندسازي و فهم بيشتر برنامه به کار ميروند و ميتوانند در هر جايي از برنامه وجود داشته باشند. هر توضيحي با کاراکتر ';' شروع ميشود و تا انتهاي خط ميتواند ادامه داشته باشد.
حالت های آدرس دهی بلاواسطه ثبات مستقیم دارای مبنا دارای اندیس دارای مبنا و اندیس
زبان اسمبلي داراي سه نوع دستور ميباشد: دستورالعمل دستور اسمبلر ماکرو
دستورالعمل: به وسيله اسمبلر به کد هدف ترجمه ميگردد و اين کدها هستند که در زمان اجرا، اجرا ميگردند. دستور اسمبلر: به اسمبلر ميگويد که عملي را انجام دهد. و اغلب هيچ اثري بر روي کد هدف ندارد. ماکرو: نوعي دستورالعمل است که در آن تعدادي دستورالعملها، دستورات اسمبلر يا حتي ماکروهاي ديگر قرار گرفتهاند.
يک دستورالعمل ميتواند شامل عناصر زير باشد: توضيحات عملوند(ها) نام دستورالعمل اسم [;comment] [operand(s)] mnemonic [name] يک کاربرد فيلم اسم آن است که ميتوان آدرس دستورالعملي را به صورت نمادي بعد از اسمبل و لينک شدن برنامه با يک برچسب نشان داد. دستورالعملهاي ديگر به راحتي ميتوانند به دستورالعمل مزبور رجوع کنند.
دستورالعملهاي داراي برچسب ميتوانند مقصد يک دستورالعمل پرش در زبان اسمبلي باشند. ساختار حلقه در زبان اسمبلي وجود ندارد، اما ميتوان حلقهها را با استفاده از jmp و يا دستورالعملهاي ديگر پيادهسازي کرد. برچسب نميتواند به وسيله عدد شروع شود. و اگر نقطه استفاده شود، حتماً بايد اولين کاراکتر باشد. بغيراز اعداد و نقطه، کاراکترهاي ديگر ميتوانند در هر موقعيتي استفاده شوند. فقط 31 کاراکتر اول اسم مورد استفاده قرار خواهد گرفت.
مقادير عددي در دستورات زبان اسمبلي، دهدهي فرض ميشوند و فقط زماني اين فرض کنار گذاشته ميشود که در برنامه منبع حالت ديگري خواسته شده باشد. يک مقدار شانزده شانزدهي بايد با يک عدد بغير از اعداد شانزدهشانزدهي «a» تا «f»، شروع شود تا اسمبلر بتواند آنها را از يک اسم تشخيص دهد.
شکل کلی برنامه START STACK _ SEG SEGMENT PARA STACK ‘STACK’ اندازه پشته. STACK _ SEG ENDS DATA _ SEG SEGMENT PARA ‘DATA’ متغیر ها DATA _ SEG ENDS EXTRA _ SEG SEGMENT PARA ‘EXTRA’ متغیرهای رشته ها EXTRA _ SEG ENDS CODE _ SEG SEGMENT PARA ‘CODE’ دستورالعمل های برنامه CODE _ SEG ENDS END START
يک برنامه از قسمتهاي مختلفي تشکيل شده است: هر کدام از اين قسمتها با دستورات اسمبلر SEGMENTو ENDS شروع شده و خاتمه يافتهاند: Segment_name SEGMENT . Segment_name ENDS دستور ENDS هيچ وقت داراي عملوند نيست؛ ولي دستور SEGMENT در بعضي کاربردها با عملوند به کار ميرود.
آخرين دستور برنامه، دستور اسمبلر زير است: END start دستور END به اسمبلر ميگويد که پردازش دستورات کد منبع را خاتمه دهد. در يک برنامه منبع فقط يک دستور END وجود دارد و آن آخرين دستور است.
عملوند start مشخص کننده اولين دستور برنامه است که بايد اجرا شود عملوند start مشخص کننده اولين دستور برنامه است که بايد اجرا شود. زماني که برنامه بار ميشود، سيستمعامل ثبات سگمنت کد را با سگمنتي که حاوي اين دستورالعمل است مقداردهي کرده و ثبات اشارهگر دستورالعملها، IP را با آفست اين دستورالعمل از ابتداي سگمنت مزبور شروع مينمايد.
Number1 DW ? Number2 DW ? هرکدام يک کلمه را در سگمنت داده ذخيره ميکنند. علامت سؤال به اسمبلر ميگويد که هيچ مقدار اوليهاي به اين دو کلمه نسبت داده نشود.
هر کدام از دستورات DB چند بايت را با مقادير اوليه داده شده ذخيره مينمايند. در هر مورد، عملوندها، مقادير اوليه را تعيين ميکنند.
سگمنت کد با دستور اسمبلر زير شروع ميشود: ASSUME CS:Code,DS:data اين دستور به اسمبلر ميگويد در صورتيکه يک دستورالعمل از يک برچسب که در داخل سگمنت کد قرار دارد استفاده بکند آدرس واقعي عملوند مزبور بايد به وسيله حاصلجمع ثبات سگمنت CS و آفست برچسب از ابتداي سگمنت کد محاسبه شود.
سيستمعامل وظيفه مقداردهي اوليه ثبات سگمنت کد را به واسطه عملوند موجود در دستور END به عهده دارد ولي سيستمعامل همين کار را براي ثبات سگمنت داده DS انجام نميدهد. اينکار را بايد برنامهنويس انجام دهد. شماره واقعي سگمنت داده تا زماني که برنامه بار نشده باشد قابل تعيين نيست، در آن زمان است که اين آدرس به وسيله DOS براي برنامه تعيين ميشود.
هيچ دستورالعملي نميتواند يک عملوند بلاواسطه را در يک ثبات سگمنت قرار دهد. ماکروي itoa يک رشته شش کاراکتري کدهاي اسکي براي عدد مکمل دو ايجاد ميکند. در يک سگمنت، ترتيب دستورالعملها دقيقاً ترتيب کدهاي حاصله را تعيين ميکند.
عملوندهاي دستورات DB و DW اسمبلر، اعداد را دهدهي فرض ميکند مگر در حالتي که داراي پسوندي باشند که به معناي ديگري اشاره کند يا اينکه به وسيله دستور اسمبلر RADIX پيشفرض را تغيير داده باشيم. يک عملوند عددي براي دستور DB ميتواند در محدوده دهدهي 255- تا 255 باشد. يک عدد بدون علامت صفر تا 255 ميتواند دريک بايت ذخيره شود. در مورد دستور DW، محدوده مجاز براي عملوندي از 65535- تا 65535 ميباشد. اعداد بدون علامت صفر تا 65535 در يک کلمه جاي ميگيرند.
عملگر DUP ميتواند براي توليد چندين بايت يا کلمه با مقادير اوليه معين و يا بدون مقدار اوليه، مورد استفاده قرار بگيرد. کاربرد اين عملگرد به DB، DW و دستورات اسمبلر ديگري که فضا را ذخيره ميکنند محدود ميشود.
دستور DW به برنامهنويس اجازه ميدهد که يک مقدار اوليه را که برابر آفست قسمت ديگري از حافظه است، نسبت دهد. اينکار شبيه به داشتن يک متغير اشارهگر است که مقدار آن آدرس بلوکي از حافظه ميباشد.
دستورات array DB 100 DUP(?) Pointer DW OFFSET array 100 بايت را براي array و يک کلمه را براي pointer ذخيره ميکنند و pointer با آفست array مقداردهي اوليه ميشود.
دستور اسمبلر DD: يک کلمه مضاعف را ذخيره ميکند DQ: هشت بايت را ذخيره ميکند. DT: ده بايت را ذخيره ميکند.
عملوند دستورالعملها عملوندها داراي انواع مختلف هستند: بعضي ثابت بوده، بعضي مشخصکننده ثباتهاي CPU ميباشند و برخي به حافظه رجوع مينمايند. به طور کلي عملوند اول، مقصد عمليات را تعيين ميکند و عملوند دوم منبع عمليات را. يک عملوند حالت بلاواسطه نميتواند بعنوان مقصد قرار گيرد.
در مواردمعدودي، برنامهنويس ممکن است يک ثبات سگمنت و يک آفست واقعي را به عنوان عملوند مستقيم بنويسد، MASM دستورالعمل زير را مجاز ميشمارد: Mov bx,dx:0014h اين دستورالعمل، ثبات BX را با کلمهاي که از بيستمين بايت سگمنت داده شروع ميشود، بار مينمايد. اين آدرس قابل جابجايي نيست. يک عملوند ثبات غيرمستقيم، از داده حافظه استفاده ميکند.
فقط چهار ثبات ميتوانند براي آدرسدهي ثبات غيرمستقيم به کار بروند: BX BP SI DI در حالت ثبات غيرمستقيم، ثبات همانند يک متغير اشارهگر در زبانهاي سطح بالا ميباشد. وقتي اندازه عملوند حافظه مبهم باشد، عملگر PTR بايد مورد استفاده قرار گيرد تا اندازه صحيح به اسمبلر داده شود.
اسمبلر، استفاده از عملوند شمارنده موقعيت يعني $ را مجاز ميشمارد، اين عملوند در زمان اسمبل شدن مقدار آفست يک دستورالعمل را نشان ميدهد. اين عملوند ميتواند در دستورالعملها يا دستورات اسمبلر مورداستفاده قرار بگيرد
ماکروي output، محتوي هيچ ثباتي و همينطور ثبات نشانهها را تغيير نميدهد. ماکروي inputs فقط بر روي ناحيه مقصد و ثبات CX اثر ميگذارد، هيچ ثبات ديگري از جمله ثبات نشانهها تغيير نخواهند کرد. ماکروي inputc داراي هيچ عملوندي نميباشد. اين ماکرو يک کاراکتر را از صفحه کليد ميخواند و کد اسکي آن را در ثبات AL ذخيره مينمايد.
اگر ماکروي atoi قادر باشد که به طور موفقيتآميز يک رشته کاراکتر اسکي را تبديل کند آنگاه نشانه سرريز يعني OF صفر خواهد گرديد. در تمام موارد نشانههاي PF,ZF,SF بسته به مقداري که در AX برگردانده ميشود به ترتيب زير تغيير خواهند کرد: اگر عدد منفي باشد SF يک خواهد شد و در غيراينصورت صفر. اگر عدد صفر باشد ZF يک خواهد شد و در حالت غيرصفر، صفر خواهد شد. PF نشاندهنده توازن عدد برگردانده شده در AX است.
نمونه كد ماشين 0000 000A a dw 10 0002 00 b db ? .code 0000 8B DF mov bx,di 0002 8A F9 mov bh,cl 0004 8B 1E 0000 R mov bx,a 0008 8A 26 0002 R mov ah,b 000C 8B 12 mov dx,[si][bp] 000E A0 0002 R mov al,b 0011 8A 26 0002 R mov ah,b 0015 BB 0003 mov bx,3 0018 B1 03 mov cl,3 001A C7 06 0000 R 0064 mov a,100 0020 C6 06 0002 R FF mov b,255
فصل چهارم دستورالعمل هاي اساسي
مطالب اين فصل انتقال اطلاعات بين مكانهاي مختلف جمع و تفريق مكمل 2 دستورالعملهاي ضرب دستورالعملهاي تقسيم جمع و تفريق مكمل 2 با اعداد بزرگ
هدف فصل هدف اين فصل ، بررسي دستورالعملهايي است ، كه براي انتقال داده ها بين مكانهاي مختلف حافظه و انجام محاسبات با اعداد صحيح مكمل دو، مورد استفاده قرار مي گيرند .
عناوين مهم فصل 1-4 انتقال داده ها بين مكانهاي مختلف حافظه 1-4 انتقال داده ها بين مكانهاي مختلف حافظه 2-4 جمع و تفريق مكمل دو 3-4 دستورالعمل هاي ضرب 4-4 دستورالعمل هاي تقسيم 5-4 جمع وتفريق مكمل دو با اعداد بزرگتر 6-4 خلاصه ي مطالب فصل
انتقال داده ها بين مكانهاي مختلف حافظه كارايي زمان و فضا (حافظه ) دو مفهوم اساسي اين فصل مي با شند . دستورالعملmov در زبان اسمبلي براي كپي كردن داده ها از محلي به محل ديگر مورد استفاده قرار مي گيرد. دستورالعمل xchg ، دستور مفيد ديگري است كه درزبان اسمبلي براي تعويض داده هاي منبع ومقصد كاربرد دارد. نكته : مي توان اندازه ي داده ي مورد نظر را از يك كلمه به يك بايت و يا بالعكس تغيير داد.
مفهوم كارايي زمان مدت زمان لازم براي اجراي يك دستورالعمل بر حسب سيكل هاي ساعت . هر چه سيكل هاي زماني براي اجراي يك دستور العمل كمتر باشد ان دستور العمل كارايي بيشتري خواهد داشت . به طور كلي دستور العملهايي كه به حافظه دستيابي مي كنند خيلي كندتر از دستورهايي هستند كه از ثبات ها استفاده مي كنند بنا براين بايد در صورت امكان داده هايي كه زياد مورد استفاده قرار ميگيرند را در ثبات ها قرارداد.
مفهوم كارايي حافظه ايجاد برنامه ي هدفي كه طول ان حداقل باشد يعني حافظه ي كمتري را اشغال كند (كد فشرده) مناسبتر وحتي در بعضي كاربرد هاي زبان اسمبلي لازم است . كارايي زمان بر حافظه ارجحيت دارد زيرا حافظه را مي توان خريد (جبران كرد ) ا ما زمان را نه ! بنابراين برنامه اي كه سريعتر اجرا شود بر ديگري برتر است حتي اگر از حافظه ي بيشتري استفاده كند.
دستورالعمل mov به صورت mov destination , source نوشته مي شود و يك بايت يا يك كلمه را از محل source به محل destination كپي مي كند . دستور العمل mov شبيه يك دستور جايگزيني ساده در زبانهاي سطح بالا مي باشد ، البته با وجود محدوديت هايي در زبان اسمبلي دستور العمل mov محتواي ثبات نشانه ها و ثبات IP ( اشاره گر دستورالعمل ها ) را تغيير نمي دهد . فرم هاي مجاز دستور العمل mov در شكل 1-4 صفحه 104 كتاب درج شده است .
محدوديت هاي زبان اسمبلي كه دستورmov را از يك دستور جايگزيني در يك زبان سطح بالا متمايز مي كند . 1- عبارتهايي نظير ( Count = 3 number + 5) را نمي توان با يك دستور mov بيان كرد . ( لازم است قبلا چند دستورالعمل براي محاسبه ي عبارت سمت راست استفاده شود . ) 2- تمام تركيبات انواع عملوندهاي منبع و مقصد مجاز نيستند .
تركيباتي ازعملوندهاي دستوالعملmov كه ممكن نمي باشند : 1- در صورتي كه هر دو عملوند منبع و مقصد در حافظه قرار داشته باشند . 2- عملوند منبع بلاواسطه به ثبات سگمنت مقصد 3- هرانتقالي به ثبات نشانه ها يا از ان 4- هر انتقالي به ثبات IP 5- انتقال از يك ثبات سگمنت به ثبات سگمنت ديگر 6- هر انتقالي كه عملوندهاي ان از يك نوع بايت يا كلمه نباشند
دستور mov وقتي كه عملوندهاي منبع و مقصد در حافظه هستند با توجه به اينكه دستورالعمل mov نمي تواند داده اي را از يك منبع حافظه به يك مقصد حافظه كپي كند ، معمولا براي انجام اين كار ازدو دستورالعمل mov كه از يك ثبات مياني استفاده مي كنند ، بهره مي گيريم . بهتر است ثبات AX را به عنوان ثبات مياني به كار ببريم زيرا از يك سيكل زماني و بايت حافظه ، كمتري نسبت به ثبات هاي ديگر استفاده مي كند . ( به صفحه 104 كتاب مراجعه شود )
دستور العمل xcgh به صورت operator2 , operator1 xcgh نوشته مي شود . و عملي را انجام مي دهد كه در زبانهاي سطح بالا با سه دستور صورت مي گيرد . اين دستور عملوند اول و عملوند دوم را با يكديگر تعويض نموده به صورتي كه به سيكل زماني و حافظه كمتري نياز داشته باشد . فرم هاي مختلف دستورالعمل xcgh در صفحه 110 كتاب است . در صورت استفاده از حافظه اصلي ، عملوند حافظه بايد عملوند دوم دستور xcgh باشد . دستورالعمل xcgh ثبات نشانه ها را تغيير نمي دهد .
نكته براي تغيير اندازه داده مورد نظر از يك كلمه به يك بايت مي توان كلمه مورد نظر را به يك ثبات انتقال داده پس بايت بالايي يا پاييني را به مقصد مورد نظر انتقال دهيم . برعكس مي توانيم دو بايت را در يك ثبات كنارهم گذاشته پس كلمه حاصل را به مقصد مورد نظر كپي كنيم .
جمع و تفريق مكمل 2 دستورالعمل هاي add و sub براي انجام جمع و تفريق با استفاده از عملوند هاي به طول يك بايت يا يك كلمه مي باشند . نكات مربوطه دستورالعمل هاي inc و dec براي افزايش ( يك واحد اضافه مي كند ) و كاهش (يك واحد كم مي كند ) يك عملوند بوده نكاتي دراين رابطه دستورالعمل neg براي منفي كردن يك عملوند ( ساختن مكمل 2 يك عدد) مي باشد . تفاوت بين دستور العمل هاي اين بخش و دستورالعمل هاي اين بخش و دستورالعمل هاي mov و xcgh يك مثال كامل
دستورالعمل add به فرم : Source , add destination است كه در صورت اجرا ، مقدار مكمل 2 در محل Source به مقدار مكمل 2 در محل destination اضافه شد و حاصل جايگزين مقدار قبلي destination مي گردد .
دستورالعمل Sub اين دستور به صورتsub destination , surce است و در صورت اجرا مقدار مكمل 2 در محل surce از مقدار مكمل 2 در محل destination كم شده و تفاضل انها جايگزين مقدار قبلي destination مي گردد تفاضل به صورت source – destination محاسبه مي شود .
نكته دردستورالعملهاي add و sub محتواي عملوند دوم ( source) تغيير نميكند. براي هر دستور add يك دستورsub متناظر با همان نوع عملوند ها، تعداد سيكل هاي زماني و تعداد بايت هاي كد هدف وجود دارد . اعمال جمع و تفريق زماني سريع ترين مي باشند كه هر دو عملوند در ثبات ها قرار داشته باشند و زماني كندترين مي باشند كه عملوند مقصد يك كلمه اي در حافظه باشد . اضافه كردن يك عملوند واقع در حافظه ي اصلي به محتواي يك ثبات سريعتر از اضافه كردن مقدار يك ثبات به محتواي يك عملوند واقع درحافظه ي اصلي مي باشند . زماني كه عملوند مقصد برابر يك كلمه است ، يك عملوند منبع بلاواسطه مي تواند برابر يك بايت باشد . زيرا در زمان اجراي عمل جمع يا تفريق به يك كلمه تبديل مي شود .
دستورالعمل هاي inc وdec دستورالعمل هاي جمع و تفريق يك منظوره مي باشند كه هميشه از عدد يك به عنوان عملوند منبع ضمني اسبفاده ميكنند. فرم اين دو دستور به صورت زيراست : inc destination dec destination
نكاتي در مورد دستورات inc وdec مقدار عملوند مقصد را به صورت يك عدد بدون علامت در نظرميگيرند. نشانه هاي OF وSF وZF را تغييرميدهند ولي نشانه CF راتغييرنمي دهند. براي افزايش و كاهش شمارنده ها مفيدند و ازدستورات جمع وتفريق متناظر كارامد ترند . بهترين مكان براي نگه داشتن شمارنده ها در صورت امكان ثبات ها مي باشند. براي اشنايي بيشتربا انواع عملوندهاي دستورات فوق به شكل 5-4 صفحه ي 118 كتاب مراجعه شود .
علت كارامد تر بودن inc وdec نسبت به add وsub درشمارنده ها دودستورadd bx , 1 و inc bx از نظركاري معادل مي باشند اما دستورadd به 4 سيكل زماني و 3بايت حافظه نياز دارد در صورتي كه دستور inc به 2 سيكل زماني و يك بايت حافظه نياز دارد. به همين ترتيب دو دستور sub counter ,1 و dec counter از نظر كاري معادل يكديگرند ولي دستور sub به23 سيكل زماني و 4 بايت حافظه نياز دارد درصورتي كه دستورdec به 21 سيكل زمان و4 بايت حافظه نيازمند است .
دستورالعمل هاي neg به صورت neg destination مورد استفاده قرار ميگيرد و تنها عملوند خود را منفي مي كند يعني مكمل 2 ان را پيدا مي كند منفي يك عدد مثبت برابر يك عدد منفي ، منفي يك عدد منفي برابر يك عدد مثبت و منفي عدد صفر برابر صفر مي شود . عملوند هاي مجاز دستور neg در شكل 6-4 صفحه 120 امده است
تفاوت تفاوت در اين است كه تمام دستورالعمل هاي add , sub , inc , dec و neg نشانه هاي ثبات نشانه ها را به روز در مي اورند . نشانه هاي ZF, SF, PF, OF, AF مطابق مقدار نتيجه دستورالعمل ها تغيير پيدا مي كنند .
مثال اين بخش با يك مثال كامل كه از دستورالعمل ها ي جديد استفاده مي كند پايان مي يابد. برنامه مقادير z,y ,x را خوانده سپس مقدار عبارت (1+2z – x+y )- را محاسبه كرده ونتيجه را نمايش مي دهد. اين برنامه در صفحه ي 123 كتاب است وبه صورت مفصل توضيح داده شده است.
دستورالعمل هاي ضرب براي ضرب از دو دستورالعمل mul و imul استفاده مي كنيم كه خيلي كندتر از دستورات جمع و تفريق مي باشند . البته mul كمي سريعتر از imul است هر كدام از اين دستورات داراي يك عملوند(منبع) مي باشند وعملوند دوم (مقصد) همواره در ثبات ax (al) قراردارد. Mul وimul كد عمل يكساني دارند اما بايت دوم كد هدفشان آنها را از يكديگر متمايز مي سازد. يك مثا ل ) برنامه اي كه با خواندن طول وعرض مستطيل مساحت ان را محاسبه مي كند در صفحه ي 132 كتاب اورده شده است)
mul وimul دستور imul عملوند هاي خود را به صورت اعداد داراي علامت در نظر مي گيرد وعلامت حاصلضرب مطابق با قوانين ضرب اعداد علامت دار تعيين ميشود . دستور mul عملوندهاي خود را به صورت بدون علامت در نظر گرفته و حاصلضرب نيز بدون علامت خو اهد بود. فرم اين دو دستوربه صورت imul source و mul source است . طول عملوند source مي تواند برابر يك بايت يا يك كلمه باشد . محتواي ان پس از عمل ضرب تغيير نمي كند . پس از عمل ضرب ممكن است مقادير نشانه هاي PF وSF وZF تغيير كنند . در دستورالعملهاي ضرب نمي توان از عملوند بلاواسطه استفاده كرد .
طول عملوند source در عمل ضرب بسته به عملوند source در دستو رالعمل هاي ضرب ، محل نگهداري عدد دوم كه بايد ضرب شود هميشه در ثبات AL يا AX مي باشد . اگر طول source يك بايت باشد ، در بايت موجود در ثبا ت AL ضرب شده و حاصل ضرب 16 بيتي درثبات AX قرار مي گيرد در صورتي كه عدد موجود درsource ، يك كلمه باشد در دو بايت ثبات AX ضرب شده و حاصل ضرب 32 بيتي در AX (16 بيت پاييني) و DX (16 بيت بالايي) قرار مي گيرد. اگر ثبات DX شامل بيت هاي با معني حاصل ضرب باشد ، دستورات mul وimul نشانه هاي CF و OF را برابر 1 قرار مي دهند. در غير اين صورت نشانه هاي مزبور برابر صفر خواهند بود .
دستورالعمل هاي تقسيم دستورالعمل هاي div و idiv براي تقسيم اعداد صحيح به كار مي روند . دستور العمل هاي تقسيم با يك مقسوم به طول مضاعف ويك مقسوم عليه به طول منفرد شروع شده ويك خارج قسمت به طول منفرد ويك باقيمانده به طول منفرد توليد مي كنند. دستورالعمل هاي cwd وcbw براي دو برابر كردن طول مقسوم قبل از عمل تقسيم مي باشند. بعد ازعمل تقسيم ، تنها عملوند آن (يعني source يا همان مقسوم عليه ) بدون تغيير باقي مي ما ند. دستورالعمل هاي تقسيم هيچ گونه مقاديرمفيدي در نشانه ها قرار نمي دهند وممكن است مقادير قبلي نشانه هاي ZF SF PF OF CF AF را پاك كنند . درحين تقسيم ممكن است خطاهايي از قبيل تقسيم بر صفرويا خيلي بزرگ بودن خارج قسمت وجا نشدن آن دريك كلمه رخ دهد كه توليد يك وقفه سخت افزاري مي نمايد .
دستورالعمل هاي idiv وdiv دستور div براي اعداد بدون علامت ودستور idiv براي اعداد علامت دار مكمل 2 مورد استفاده قرار مي گيرند.فرم دستورالعمل هاي تقسيم به صورت زير است : idiv source و div source كه داراي يك عملوند (source) مي باشند كه به عنوان مقسوم عليه به كار مي روند . مقسوم مورد نظربا توجه به طول source در ثبات AX يا در ثبات هايAX وDX قرار دارد . بعد از عمل تقسيم ، خارج قسمت و باقيمانده با توجه به طول مقسوم در ثبات هاي خاصي قرار مي گيرند. علامت باقيمانده هميشه مساوي علامت مقسوم است.
طول عملوند دستورالعملهاي تقسيم (source ) و محل قرارداشتن مقسوم اگرعملوند (source) يا همان مقسوم عليه به طول يك بايت باشد مقسوم به طول يك كلمه بوده وبايد در ثبات AX قرار داشته باشد واگر عملوند source به طول يك كلمه باشد ، مقسوم به طول يك كلمه مضاعف بوده وبايد 16 بيت پاييني آن درثبات AX و16 بيت بالايي آن در ثبات DX قرار داشته باشد.
طول مقسوم ومحل قرار گرفتن خارج قسمت وباقيمانده پس از تقسيم يك كلمه مضاعف (مقسوم به طول 32 بيت ) كه در ثبات هاي AX وDX قرار دارد به يك مقسوم عليه به طول كلمه (16بيت ) خارج قسمت درثبات AX وباقيمانده در ثبات DX قرار خواهد گرفت و پس از تقسيم يك كلمه كه درثبات AX قرار دارد به يك مقسوم عليه به طول يك بايت خارج قسمت در ثبات AL و باقي مانده در ثبات AH قرار مي گيرد .
جمع و تفريق مكمل 2 با اعداد بزرگتر اگردرانجام محاسبات، با اعداد بزرگ (فراترازمحدوده 32767 تا32768-) سروكارداشته باشيم بايد از دستورالعمل هاي ويژه يعني adc وsbb براي جمع وتفريق آنها استفاده كنيم . انواع عملوند هاي مجاز دستورات adc وsbb درشكل 4-15 ، صفحه 147 كتاب مشاهده مي شود. نشانه ي cf رامي توان توسط سه دستورالعمل clc وstc وclc كنترل كرد.
دستورالعمل adc براي جمع اعداد بزرگ ،ابتدا همانند دستور add ، 16 بيت پاييني با يكديگر جمع شده ونشانهcf با توجه به رقم نقلي از بيت مرتبه بالايي ، مقدارصفر يا يك را به خود اختصاص مي دهد. پس با استفاده ازدستور adc ، 16 بيت بعدي با هم جمع شده ، به اين ترتيب كه در صورت 1 بودن cf حاصل جمع 16 بيت بعدي با عدد 1 نيز جمع شده ودرمقصد قرار مي گيرد ودر صورت صفر بودن cf ، 16 بيت بعدي همانند دستور add با هم جمع مي شوند.
دستورالعمل sbb اين دستور براي تفريق اعداد بزرگ مورد استفاده قرار مي گيرد. در هر بار 16 بيت از سمت راست به چپ تفريق مي شوند ، همانند دستورالعمل sub ، مگر اينكه نشانه ي CF برابر1 باشد كه درآن صورت يك واحد از تفاضل كاسته مي شود.
كنترل كردن نشانه CF دستورالعمل clc : نشانه ي cf را برابر صفر قرار مي دهد. 0 CF : = دستورالعمل stc : نشانه ي cf را برابر 1 قرارمي دهد. CF : = 1 دستورالعمل cmc : نشانه ي cf را مكمل مي كند.
خلاصه مطالب براي انتقال داده ها از يك محل به محل ديگر از دستور mov استفاده ميشود براي جابجايي محتواي دو محل از حافظه از دستور xchg استفاده ميشود عمل جمع با دستور add و تفريق با sub صورت ميگيرد دستورالعمل inc براي يك واحد افزايش و dec براي يك واحد كاهش كه كاربرد زيادي در حلقه هاي تكرار دارند دستورات imul و idiv ضرب و تقسيم مكمل 2 هستند دستورات mul و div ضرب و تقسيم اعداد بدون علامت هستند. براي جلوگيري از خطاي تقسيم طول مقسوم را با دستورات cbw و cwd دوبرابر ميكنيم
خلاصه مطالب دستورات adc و sbb براي عمليات جمع و تفريق با استفاده از بيت سرريز يا قرضي و به منظور جمع و تفريق اعداد طولاني بكار ميروند دستورات clc و stc و cmc براي پاك كردن و روشن كردن و مكمل كردن نشانه cf بكار ميروند دستورالعملهايي كه عملوند آن در داخل ثباتها قرار دارند از سرعت بيشتري برخوردارند دستورات ضرب و تقسيم بسيار كندتر از جمع و تفريق اجرا ميشوند
فصل پنجم انشعاب و حلقه
مطالب اين فصل پرشهاي غير شرطي پرشهاي شرطي دستورات مقايسه و ساختارهاي if پياده سازي حلقه هاي for , until , while حلقه هاي for در زبان اسمبلي آرايه ها
پرشهاي غير شرطي Jmp statement_label که در آن statemaet_label متناظر با فيلد اسم دستور اسمبلي ديگري ميباشد. دستور JMP شبيه به goto در پاسکال يا بيسيک است.
اگر شرايط مختلفي وجود داشته باشد که تحت آن شرايط برنامه بايد خاتمه پيدا کند، ميتوان به يک دستور اجرايي که به وسيله برچسب quit: مشخص شده است و محل اختتام برنامه ميباشد، پرش نمود.
فرمهاي درون سگمنتي وقتي توليد ميشوند که مقصد در درون سگمنت جاري قرار داشته باشد، اين فرمها در بين انواع ديگر از همه رايجتر ميباشند. پرشهاي بين سگمنتي که به عبارتي به يک سگمنت کد ديگر پرش ميکنند، به ندرت مورد نياز ميباشند. پرشهاي غيرمستقيم مقدار جابجايي خود از دستورالعمل مقصد را، از يک ثبات يا از يک کلمه در حافظه به دست ميآورند. پرشهاي درون سگمنتي نسبي، از انواع ديگر معمولتر بوده و بيشتر مورد استفاده قرار ميگيرند.
هرکدام از اين دستورالعملهاي jump شامل يک جابجايي از مقصد نسبت به خود دستور ميباشند. اين مقدار جابجايي به آفست دستوربعدي اضافه ميشود تا آفست مقصد به دست ميآيد.
در زماني که پرش به قبل از دستور jmp باشد، MASM ميتواند تعيين کند که مقصد کجاست و در صورت امکان از يک مقدار جابجايي کوتاه استفاده ميکند. زماني که پرش به بعد از دستور JMP باشد، ماکرواسمبلر مقدار جابجايي دستور مقصد را نميداند و بايد تصميم بگيرد که چه مقدار فضا براي JMP قرار دهد، بنابراين فضاي جابجايي 16 بيتي را براي آن در نظر ميگيرد. اگر جابجايي، فقط به يک بايت نياز داشته باشد، به جاي بايت اضافي، دستورالعمل NOP را قرار ميدهد. اين دستور هيچ کاري انجام نميدهد و فقط يک بايت را اشغال ميکند.
زماني که بخواهيم به دستوري بعد از دستور JMP پرش کنيم و بدانيم که اين دستور داراي فاصله زيادي نميباشد ميتوانيم به وسيله عملوند SHORT به ماکرواسمبلر بگوييم که از مقدار جابجايي کوتاه استفاده کند. بدين ترتيب يک بايت در کد هدف صرفهجويي ميشود.
پرشهاي شرطي، دستورات مقايسه و ساختارهاي If شکل کلي آنها به اين صورت است: j--- target_statement در آن آخرين قسمت دستور تعيينکننده وضعيتي است که تحت آن، پرش اجرا ميشود. اگر شرط تحقق يابد، پرش صورت خوهد گرفت، در غيراينصورت دستورالعمل بعدي اجرا خواهد شد.
دستورالعملهاي پرش شرطي در وضعيت فلگها، تغييري ايجاد نميکنند و فقط نسبت به وضعيت آنها عکسالعمل نشان مي دهند.
JZ end_while اين دستور به اين معني است که اگر فلک ZF برابر با يک است به دستورالعملي با برچسب end_while پرش کن و در غير اين صورت به دستور بعدي برو.
چندين برچسب ميتوانند دستورالعملهاي بعد از ساختار if را آدرسدهي نمايند. از آنجايي که برچسبها جزء کدهدف برنامه نيستند، برچسبهاي اضافي به طول کد هدف يا زمان اجراي برنامه چيزي را اضافه نميکنند. براي پيادهسازي يک طرح غالباً از برچسبهايي مثل if ، then و else و endif استفاده ميشود. هيچ کلمه رزرو شدهاي حاوي کاراکتر خط زيرين (underscore) نيست.
دستورCMP: CMP operand_1 , operand-2 اين دستور عملوند operan_2 را از عملوند operand_1 تفريق ميکند، درست همانند دستورالعمل sub. مقدار تفاضل و چيزهايي که در اين عمل تفريق اتفاق ميافتند وضعيت فلگها را تعيين ميکنند. تفاوت آن با sub اين است که بر خلاف sub عملوند operand_1 را تغيير نميدهد.
اين دستور دو عملوند را با يکديگر مقايسه ميکند و سپس فلگهاي AF,CF,OF,PF و ZF را برابر يک يا صفر مينمايد. تنها وظيفه دستور CMP آن است که مقدار فلگها را تعيين کند. اين کار وظيفه اوليه اين دستورات است نه وظيفه جانبي.
فلگ رقم نقلي يعني CF زماني برابر يک ميشود که در تفريق يک رقم عاريه وجود داشته باشد، چنانچه عاريه وجود نداشته باشد اين فلگ برابر صفر خواهد بود. فلگ سرريزي يا OF در صورتي يک خواهد بود که سرريزي وجود داشته باشد و در غير اينصورت برابر صفر خواهد بود. فلگ علامت يا SF زماني يک خواهد بود که حاصل تفريق نشان دهنده يک عدد منفي مکمل دو باشد و زماني برابر صفر خواهد بود که حاصل تفريق برابر صفر يا مثبت باشد. فلگ صفر يا ZF زماني يک خواهد بود که حاصل تفريق صفر باشد و در غير اينصورت برابر صفر خواهد بود.
راه تشخيص کوچکتر بودن يک عملوند از عملوند ديگر آن است که فلگ علامت سرريزي را مقايسه کنيم؛ در زماني که operand_1 کوچکتر از operan_2 باشد، اين فلگها متفاوت با يکديگر هستند و زماني که operand_1 بزرگتر يا مساوي operand_2 باشد، اين فلگها وضعيت مشابهي خواهند داشت.
در بسياري از اين پرشها رابطه بين دو عملوند دستورالعمل cmp موردنظر ميباشد و نه وضعيت فلگها. وقتي اولين عملوند در حافظه باشد، دستورات cmp به پالسهاي ساعت کمتري نسبت به دستورالعملهاي sub مربوطه نياز دارند، زيرا نيازي به ذخيره کردن نتيجه نخواهد بود.
همه دستورات زير مجاز هستند: Cmp ax,356 Cmp pattern,0D3a6h cmp bh,'$' توجه داشته باشيد که يک عملوند بلاواسطه بايد دومين عملوند باشد؛ به اين دليل، دستورالعمل زير مجاز نيست Cmp 100,total ;illegal
براي تعيين نامساويها دوسري نام وجود دارد و اينها کدهاي ماشين متفاوتي را توليد ميکنند. يکسري از آنها بيشتر به فلگ رقم نقلي توجه دارند و بنابراين متناسب کار با اعداد بيعلامت ميباشند. مجموعه ديگر پرشهاي شرطي براي تعيين ترتيب به فلگ علامت و فلگ سرريزي توجه دارند.
هيچ شکل جايگزين ديگري براي دستورالعملهاي پرش شرطي جهت پرشهاي طولانيتر وجود ندارد. گاهي اوقات پرشهاي شرطي بايد با پرشهاي غيرشرطي ترکيب شوند تا به هدفهايي که در فواصل طولانيتر قرار دارند برسيم.
پيادهسازي حلقههاي while، until و for While: . ;code to check Boolean expression . Body: . ;loop body Jpm While ;go check condition again End_While
شرط ادامه که يک عبارت بولي است در ابتدا بررسي ميگردد، چنانچه صحت داشته باشد، آنگاه بدنه حلقه اجرا ميشود و دوباره شرط ادامه بررسي ميشود. هر زماني که عبارت بولي صحت نداشته باشد، اجرا با دستورالعمل بعد از end_While ادامه پيدا ميکند. البته اگر بدنه حلقه بيش از 127 بايت طول داشته باشد هيچکدام از اين عبارتها صحيح نخواهد بود زيرا پرش نسبي خارج از محدوده مجاز خواهد بود.
غالباً شرط ادامه در يک حلقه While ساده نبوده و داراي دو قسمت است که به وسيله عملگرهاي بولي and يا or با يکديگر ترکيب ميشوند. در عملگر and هر دو عملوند بايد صحت داشته باشند تا کل شرط صحت داشته باشد و در عملگر or فقط زماني نتيجه عملگر or صحت ندارد که هر دو عملوند آن صحت نداشته باشد.
گاهي اوقات پردازش يک حلقه تا زماني که با مقادير نرمال برخورد شود، بايد ادامه پيدا کند و وقتي با مقدار خاصي برخورد ميشود، متوقف ميگردد. يک مزيت زبان اسمبلي آن است که قابليت انعطاف بيشتري در برنامهنويسي وجود دارد.
طرح زير ميتواند براي گرفتن دادهها از صفحه کليد به کار رود: While واردشده از صفحه کليد برابر مقدار موردنظر نيست) value) loop . . . [بدنه حلقه] End While;
در ماکروي atoi چنانچه کاراکتر اسکي به عدد منفي تبديل شود فلگ علامت (SF) يک ميشود و در غير اينصورت صفر ميگردد. بدنه حلقه for، حلقهاي که به وسيله يک شمارنده کنترل ميشود، براي هر مقدار شاخص حلقه در يک محدوده معين يکبار تکرار ميشود. براي حلقهاي for در زبان اسمبلي، شاخصهاي معمولاً اعدا صحيح هستند.
براي مواردي مطلوبست که تعداد دفعات تکرار از قبل معلوم باشد. For شاخص : = مقدار ابتدايي to مقدار انتهايي loop . . . {بدنه حلقه} End for: بک حلقه for به راحتي ميتواند به ساختار while ترجمه گردد.
يک حلقه until ميتواند به صورت زير بيان شود: until شرط خاتمه loop . . . {بدنه حلقه} End until; بدنه حلقه حداقل يکبار اجرا شده و سپس شرط خاتمه بررسي ميشود. اگر شرط خاتمه برقرار نباشد بدنه حلقه دوباره اجرا ميشود و اگر برقرار باشد، اجرا برنامه از دستورات بعد از end until ادامه پيدا ميکند.
ساختارهاي حلقهاي ديگر نيز ميتوانند به زبان اسمبلي پيادهسازي گردند ساختارهاي حلقهاي ديگر نيز ميتوانند به زبان اسمبلي پيادهسازي گردند. حلقه forever اغلب مفيد است و در هر جايي که به کار رود، هميشه داراي يک جمله خروج براي انتقال کنترل به انتهاي حلقه ميباشد، اين جمله اغلب شرطي است مثل يک دستورالعمل if .
Forever loop . if (respons='s') or (response = 's') then exit loop endif; end loop;
حلقههاي for در زبان اسمبلي: دستورالعمل loop داراي شکل زير ميباشد: Loop statement_label در اين دستور statement_label، برچسب دستورالعملي است که داراي يک جابجايي کوتاه نسبت به دستور loop است. دستور loop باعث ميشود که اعمال زير صورت پذيرند: مقدار ثبات CX کاهش پيدا ميکند. اگر مقدار ثبات CX صفر باشد، آنگاه اجرا از اولين دستور بعد از دستورالعمل loop ادامه پيدا ميکند. اگر مقدار ثبات CX صفر نباشد، آنگاه پرش به آدرسي که statement_label مشخص ميکند، صورت ميگيرد.
دستورالعمل loop به دو بايت کد هدف نياز دارد، بايت اول، بايت کد عمل است و دومين بايت مقدار جابجايي به دستورالعمل مقصد ميباشد. دستور Loop وضعيت هيچ فلگي را تغيير نخواهد داد. دراين دستورالعملها هيچ ثبات ديگري نميتواند به جاي CX به کار برود. در عمل اين به آن معني است که وقتي دستورالعمل LOOP به کار ميرود، ثبات CX نميتواند به منظورهاي ديگر به کار برده شود.
دستورالعمل پرش شرطي JCXZ به اين منظور به کار ميرود که اگر محتواي ثبات CX صفر باشد به مقصدي که براي آن تعيين ميکند پرش کند. اين دستور همانند دستورالعملهاي پرشي ديگر به دو بايت کد هدف نياز دارد و بر روي فلگها هيچ اثري نميگذارد.
از آنجايي که دستورالعمل dec فلگ صفر (ZF) را يک يا صفر ميکند، دستورالعمل پرش شرطي زير که کمي سريعتر ميباشد، ميتواند به جاي دستورالعمل JCXZ به کار برود.
Jz end_for اغلب راحتتر است که براي پيادهسازي يک حلقه for از دستورالعمل loop استفاده شود حتي زماني که شاخص حلقه افزايش پيدا ميکند و بايد در بدنه حلقه مورد استفاده قرار گيرد. دستورالعمل loop ازثبات CX براي کنترل تعداد تکرارهاي استفاده ميکند. Loopz statement_label چنانچه مقدار جديدي در ثبات CX صفر باشد و فلگ صفر، يک باشد، دستورالعمل loopz به دستورالعملي که در statement_label قرار دارد، پرش ميکند.
Loopnz statement_label چنانچه مقدار جديد در ثبات CX صفر نباشد و فلگ صفر برابر صفر باشد، دستورالعمل loopnz به دستورالعملي که در statement_lable قرار دارد، پرش ميکند. همانند دستورالعمل loop، دستورالعملهاي loopz و loonz بر روي هيچ فلگي اثر نميگذارند.
آرايهها Lea destination,source نام lea يعني «آدرس مؤثر را بار کن» ميباشد. Destination بايد يک ثبات عمومي 16 بيتي بوده و source هرگونه رجوعي به حافظه است. آدرس source در ثبات بار ميشود.
دستورالعمل lea نسبت به mov قابليت انعطاف بيشتري را با توجه به نوع عملوند منبع در اختيار ميگذارد. با استفاده از آدرسدهي غيرمستقيم ثبات ميتوان به صورت تصادفي دسترسي پيدا نمود.
Lea bx,nbr_array ;starting address of array به طور مثال، عبارت array [count] را به مجموع اضافه کن» ميتواند به ترتيب زير پيادهسازي شود، البته با اين فرض که ثبات CX به عنوان شمارنده و ثبات AX بعنوان مجموع به کار برود: Mov dx,cx ;count Dec dx ;count-1 Add dx,dx ;2*(count-1) Lea bx,nbr_array ;starting address of array Add bx,dx ;address of nbr_array [count] Add ax,,[bx] ;add array [count] to sum تکنيک به کار رفته در اينجا آن است که تعداد بايتهاي قبل از عنصر موردنظر را جمع کرده و اين عدد را به آدرس شروع آرايه اضافه کرد.
پرشهاي غير شرطي دستور JMP این دستور مانند دستور GOTO در بیسیک و پاسکال است JMP statement_label Statement_label اشاره به برچسب دستوری دارد که قرار است پرش به آن صورت گیرد
پرشهاي غير شرطي مثال پرش به اولین دستورالعمل خروج Jmp quit; . بازگشت مقدار صفر در رجیسترQuit : mov al ,0;
انواع پرش مستقیم نسبی درون سگمنت کوتاه نسبی درون سگمنتی غیر مستقیم درون سگمنتی مستقیم بین سگمنتی غیر مستقیم بین سگمنتی
if پرشهاي شرطي دستورات مقايسه و ساختارهاي حالت کلی دستور به شکل زیر است به جز یک استثنا در بقیه موارد عبارت پس از j که معمولا به نتیجه ثبت شده در فلاگها اشاره میکند تعیین شرط پرش مینماید J --- TARGET _ STATEMENT
نمونه های پرش شرطی Jz پرش در صورت صفر بودن Jnz پرش در صورت صفر نبودن Js پرش در صورت منفی بودن Jns پرش در صورت مثبت بودن
دستور مقایسه دستور CMP جهت مقایسه دو مقدار استفاده میشود برای تغییر حالت فلاگها که منجر به دستور پرش خواهد شد میباید عبارت شرط را با این دستور ارزیابی کنیم شکل کلی دستور به صورت زیر است Cmp operand_1 , operand_2
پياده سازي حلقه هاي for , until , while برای پیاده سازی حلقه ها در اسمبلی مانند دستور if از cmp و j… استفاده میشود در حالت کلی عبارت مقایسه در ابتدا و عبارت پرش در انتهای کد ظاهر میشود در حلقه for علاوه بر این اندیس حلقه در یک رجیستر با دستور inc یا dec افزایش یا کاهش می یابد
for حلقه های حلقه های for در زبان اسمبلی با شبیه سازی حلقه while بوجود می آید ابتدای شروع حلقه اندیس حلقه مقدار دهی شده دستور مقایسه در ابتدای حلقه اندیس را با مقدار انتهایی مقایسه و درصورت رسیدن به مقدار نهایی به دستورالعما انتهایی پرش میکند در داخل حلقه اندیس افزایش یا کاهش می یابد یک پرش غیر شرطی به ابتدای حلقه
در زبان اسمبلی رجیسترهای زیر برای عملیات آرایه ای در نظر گرفته شده اند آرايه ها در زبان اسمبلی رجیسترهای زیر برای عملیات آرایه ای در نظر گرفته شده اند SI , DI , BP ذخیره سازی آرایه ها با دستور dup در برنامه اسمبلر و با دستور DW در سگمنت داده صورت میگیرد
فصل ششم روال ها
مطالب اين فصل بدنه يك روال دستورالعملهاي call , return دستورالعملهاي push , pop انتقال مقادير به يك روال و بالعكس بازگشت پذيري (recursion)
روالها کلمه روال در زبان پاسکال و ساير زبانهاي برنامهنويسي سطح بالا براي بيان زير برنامهاي که تقريباً يک واحد کاملي ميباشد، بکار ميرود.
آرگومانها بايستي متناظر با پارامترهاي مجازي روال مزبور باشند آرگومانها بايستي متناظر با پارامترهاي مجازي روال مزبور باشند. در زبان پاسکال نوع ديگري از زير برنامه به نام تابع وجود دارد. يک تابع در زبان پاسکال شبيه يک روال ميباشد بجز اينکه آن را در داخل يک عبارتي با ذکر نام و آرگومانهاي مربوطه در داخل پرانتز، فراخواني ميکنيم. يک تابع مقداري را بر ميگرداند که اين مقدار در عبارت مربوطه مورد استفاده قرار ميگيرد.
آدرس برگشت به برنامه فراخواننده زير برنامه روي پشته ذخيره ميشود ميتوان مقادير ثباتها در زمان فراخواني يک زيربرنامه را روي پشته ذخيره نموده و در زمان برگشت به برنامه فراخواننده مقادير ثباتها را با استفاده از پشته بازسازي نمود، با استفاده از پشته ميتوان آرگومانها را به يک زيربرنامه انتقال داده و يا مقاديري را از يک زيربرنامه فراخواننده انتقال داد، و حتي ميتوان فضاي لازم براي متغيرهاي محلي را روي پشته تخصيص داد.
بدنه يک روال؛ دستورالعملهاي CALL و RETURN بدنه يک رواي در داخل دستورات PROC و ENDR قرار ميگيرد و هر کدام از دستور العملها داراي بر چسبي است که برابر نام روال مزبور ميباشد. بعلاوه، دستور PROC شامل يکي از عملوندهاي NEAR يا FAR ميباشد. يک روال NEAR در همان سگمنت کدي که فراخواني مي شود تعريف ميگردد، و يک روال FAR معمولاً در يک سگمنت کد مجزايي تعريف ميشود.
اجراي يک برنامه لزوماً از اولين دستورالعمل سگمنت کد شروع نميشود، بلکه از دستورالعمل مشخص شده توسط عملوند دستور END که پايان برنامه را نشان ميدهد، شروع ميشود. بطور کلي، يک روال را ميتوان هر چند بار فراخواني کرد. دستور العمل برگشت کنترل اجرا را از روال به برنامه اصلي برميگرداند؛ معمولاً حداقل يک دستورالعمل ret در يک روال وجود دارد که البته ميتواند بيش از يک دستورالعمل ret وجود داشته باشد.
زماني که پشته براي ذخيره کردن مقاديري بکار ميرود، يک يا چند کلمه ذخيره ميشود، هرگز يک بايت تکي ذخيره نميشود. براي ذخيره کردن يک کلمه، ثبات SP باندازه 2 واحد (بايت) کاهش مييابد.
يک کلمه روي پشته ذخيره شده وضعيت اوليه پشته SP ** يک کلمه روي پشته ذخيره شده وضعيت اوليه پشته SP SS
توجه داشته باشيد که با ذخيره شدن کلمات روي پشته، مقدار ثابت SS تغيير نکرده بلکه تنها ثابت SP تغيير پيدا ميکند. زماني که دستورالعمل Call اجرا ميشود، افست دستورالعمل بعد از call را روي پشته ذخيره ميکند. سپس ثبات IP برابر افست روال قرار داد شده و اجراي برنامه از دستورالعمل واقع در آدرس CS:IP يعني اولين دستورالعمل روال مزبور ادامه مييابد. با توجه به اينکه برنامه اصلي و روال مزبور در داخل يک سگمنت قرار دارند، نيازي به تغيير شماره سگمنت واقع در ثبات CS وجود ندارد.
زماني که دستور العمل ret اجرا ميشود، کلمه واقع در بالاي پشته بازيابي شده و در ثبات IP ذخيره ميگردد. سپس اجراي برنامه از دستورالعمل واقع در آدرس IP:CS يعني از دستورالعمل بعد از call در برنامه اصلي ادامه پيدا ميکند. اين نوع فراخواني يا برگشت را فراخواني يا برگشت درون يک سگمنت گويند.
فرم دور(far) يک دستوالعمل فراخواني ابتدا محتواي ثبات CS را روي پشته ذخيره کرده و شماره سگمنت حاوي روال مورد نظر را داخل ثباتCS قرار ميدهد. سپس افست دستورالعمل بعدي را روي پشته ذخيره کرده و افست روال مزبور (در داخل سگمنت کد جديد) را در ثبات IP قرار ميدهد. جمعاً چهار بايت ناحيه پشته مورد استفاده قرار ميگيرد. فرم دور يک دستورالعمل ret عکس اين مراحل را انجام ميدهد، ابتدا ثبات IP را برابر افست دستورالعمل بعد از فراخواني اوليه قرار داده و سپس ثبات CS را برابر شماره سگمنت برنام فراخواننده قرار ميدهد؛ اين دو کلمه از داخل پشته کپي ميشوند.
Call procedure عملوند procedure معمولاً برابر نام روال مورد نظر ميباشد، ولي ميتواند با استفاده از آدرسي در داخل يک ثبات يا در حافظه بطور غير مستقيم بکار رود.
دستور العمل ret داراي دو فرم مختلف است Ret pop –value (2 عملوند pop –value پس از اتمام ساير مراحل فرآيند برگشت (بازسازي ثبات IP و در مورد يک روال دور، بازسازي مقدار ثبات CS) به محتواي ثبات SP افزوده ميشود.
از اين فرم ميتوان در مواردي که کلماتي (بعضي مواقع مقادير پارامترها) روي پشته ذخيره شده و ميخواهيم آنها را در زمان خروج از روال بطور منطقي حذف کنيم، استفاده کرد.) براي ساختن بلوکهاي تشکيل دهنده برنامههاي بزرگ معمولاً يک روال يا گروهي از روالها را بطور مجزا اسمبل ميکنيم.
دستور PUBLIC Procedurel,Procedure2 به اسمبلر و لينکر ميگويد که برچسبهاي procedure1 و procedure2 ممکن است به وسيله برنامههايي که به طور مجزا اسمبل شدهاند، مورد استفاده قرار بگيرند.
برنامهاي که اين روالها را فراخواني ميکند بايستي شامل يک يا چند دستور EXTRN باشد که به اسمبلر بگويد که برچسبهاي Procedurel و Procedurel2 خارجي (exretnal) بوده و بطور محلي تعريف نشدهاند.
معمولاً دستورات EXTRN در ابتداي برنامه مربوطه ذکر ميشوند معمولاً دستورات EXTRN در ابتداي برنامه مربوطه ذکر ميشوند. با استفاده از يک دستور، فرم دستور EXTRN بصورت زير است: EXTRN Procedure 1:FAR, procedure 2:FAR فرض کنيد که فايلهاي استفاده شده براي برنامه اصلي و روالها به ترتيب ASM.MAIN و PROCS.ASM باشند.
براي ساختن يک برنامه قابل اجرا مراحل زير لازم ميباشد: با استفاده از MASM فايلهاي MAIN و PROCS را اسمبل کنيد (هر کدام را بخواهيد اول اسمبل کنيد) باين ترتيب دو فايل OBJ . بنامهاي OBJ. MAINو PROCS.OBJ ساخته ميشوند. با استفاده از LINK برنامه اصلي و روالها را با ذکر "main+procs+io" بعنوان ماژولهاي هدف به يکديگر پيونده دهيد (بطور کلي واحدهاي OBJ. مورد نظر را با کاراکتر «+» از يکديگر جدا کنيم. واحد io تنها زماني مورد نياز ميباشد که از ماکروهاي فايل IO.H استفاده کرده باشيد.) LINK معمولاً نام برنامه EXE را برابر نام اولين واحد OBJ قرار ميدهد؛ ميتوانيد نام واحدهاي OBJ. را به هر ترتيبي ذکر کنيد.
بدنبال اين مراحل، ميتوانيد با دادن نام فايل EXE بدنبال اين مراحل، ميتوانيد با دادن نام فايل EXE. به سيستم عامل DOS آن را اجرا کنيد. ثباتهاي همگاني AX، BX، CXو DX بوسيله دستورالعملهاي call و ret تغيير پيدا نکرده و نه داراي وظائف مشخص ديگري ميباشند، از اين رو ميتوانيم از اين ثباتها براي انتقال مقادير باندازه کلمه به روالها و بالعکس، استفاده کنيم.
دستورالعملهاي PUSH و POP؛ دادههاي محلي بمنظور ذخيره کردن محتواي يک ثبات يا کلمه حافظه اصلي، مقدار مورد نظر معمولاً بعد از شروع اجراي يک روال روي پشته ذخيره شده و قبل از اجراي دستور العمل برگشت از روال آن را روي پشته بازيابي ميکنيم.
Push Source عملوند Source ميتواند هر ثباتي بجز ثبات نشانهها و ثبات اشارهگر دستورالعملها يعني IP بوده و يا ميتواند کلمهاي در حافظه اصلي را ارجاع دهد. يک عملوند بلاواسطه مجاز نميباشد. دستورالعملهاي push و pop هيچکدام ثبات نشانهها را تغيير نميدهند.
دستورالعمل push از پشته دقيقاً مانند دستور العمل Call استفاده ميکند دستورالعمل push از پشته دقيقاً مانند دستور العمل Call استفاده ميکند. اشارهگر پشته SP باندازه دو بايت کاهش يافته و سپس کلمه آدرس داده شده بوسيله عملوند منبع در دو بايت با آدرس SS:SP ذخيره ميشود. البته، اجراي برنامه بجاي اولين دستورالعمل روال مربوط در دستورالعمل Call، با دستور العمل بعدي ادامه پيدا ميکند.
از دستورالعملهاي Push و POP معمولاً بصورت زوج استفاده ميشود. POP destination که destination ميتواندکلمهاي در حافظه اصلي را ارجاع داده و يا ميتواند هر ثباتي بجز ثبات نشانهها و ثبات اشارهگر دستور العملها IP و ثبات سگمنت کد CS باشد. از دستورالعملهاي Push و POP معمولاً بصورت زوج استفاده ميشود.
دستورالعمل Pushf (ذخيره کردن نشانهها) 16 بيت نشانهها را (حتي آنهائي را که معني خاصي بعنوان نشانه ندارند) روي پشته ذخيره کرده و دستورالعمل popf (بازيابي نشانهها) نشانهها را از روي پشته بازيابي ميکند.
در روالهاي پيچيده غالباً نياز به دستيابي دادههاي ذخيره شده در حافظه اصلي وجود دارد. يک روش از يک سگمنت داده مجزا استفاده ميکند، و روش ديگر دادههاي را در همان سگمنت کد روال ذخيره ميکند.
دستور ASSUME CS: proc_code,ds: poc_data به اسمبلر ميگويد فرض کند که ثبات CS در زمان اجراي دستورالعملهاي بعدي به سگمنت proc-code اشاره کرده و ثبات DS به سگمنت proc-data اشاره خوهد کرد. بکمک اين دستور، اسمبلر افستهاي متغيرها در داخل proc-data را از اول اين سگمنت و افستهاي دستورالعملها در داخل proc-code را از اول اين سگمنت محاسبه خواهد کرد.
در فراخواني يک روال، يک مقدار جديد بعنوان نتيجه دستورالعمل call بطور اتوماتيک در داخل ثبات DS قرار نميگيرد. اين وظيفه برنامهنويس است که محتواي ثبات DS مربوط به برنامه فراخوانند را ذخيره کرده، ثبات سگمنت داده جديد را بار کرده و قبل از بازگشته به برنامه فراخواننده، مقدار اوليه ثبات DS را بازسازي کند.
انتقال مقادير به يک روال و بالعکس: دو روش ممکن براي انتقال يک مقدار باندازه کلمه عبارتند از: قرار دادن مقدار مورد نظر در يک ثبات قرار دادن مقدار مورد نظر روي پشته
در آدرس دهي مبنا، افست يک محل حافظه بصورت مجموع محتواي يک ثبات مبنا (ثبات BP يا BX) و عددي که در داخل دستورالعمل قرار دارد، محاسبه ميشود.
نشان گذاري براي آدرس دهي مبنا: [bp+number] براي ثبات BPو از نشان گذاري [bx+number] براي ثبات BX استفاده ميکند. اگر ثبات BP استفاده شود، در اين صورت افست در سگمنت پشته قرار دارد؛ يعني آدرس حقيقي برابر [BP+number] :SS ميباشد از طرف ديگر، اگر ثبات BX استفاده شود، در اين صورت افست در سگمنت دادهها قرار دارد؛ يعني آدرس حقيقي برابر [BP+number] :DS ميباشد.
غالباً ميخواهيم پس از برگشت به برنامه فراخواننده مقدار ثبات BP تغيير پيدا نکند، در اين صورت مقدار BP بايستي در اول روال و قبل از کپي کردن مقدار ثبات SP بداخل ثبات BP، بر روي پشته اضافه گردد. بايد ترتيب هر کدام از آرگومانها باندازه دو بايت نسبت به SS:BP دورتر باشند. با فرض اينکه روال مزبور بصورت FAR تعريف شده باشد، در اين صورت آرگومان دوم در افست (BP+6) و آرگومان اولي در افست (BP+8) خواهد بود. اگر بخواهيد ثباتهاي ديگري را ذخيره کنيد ميتوانيد اين کار را بعد از کپي کردن ثبات SP بداخل BP انجام دهيد.
نقطه قوت اين سيستم اين است که پس از ثابت نگهداشتن ثبات BP، ميتواند پشته را بطور آزاد براي هر منظوري استفاده کرد و در نتيجه ثبات SP را تغيير داد، در حالي که ميتوان با استفاده از ثبات BP آرگومانها را دستيابي کرد.
اگر برنامهاي به اضافه کردن آرگومانها روي پشته و فراخواني روالها ادامه دهد، در اين صورت برنامه اصلي و يا روالهاي مربوطه بايستي اين مقادير را از پشته حذف کنند که در غير اين صورت ممکن است پشته سر زير نمايد. برنام اصلي ميتواند اين کار را انجام دهد که تعداد بايتهائي را که بايستي آزاد شوند به ثبات SP اضافه کند. اگر از پشته براي برگرداندن يک يا چند مقدار به برنامه اصلي استفاده شود، هيچکدام از اين تکنيکها بدون تغيير کار نخواهد کرد.
بازگشت پذيري (Recursion) يک روال يا تابع بازگشتي روال يا تابعي است که بطور مستقيم يا غير مستقيم خودش را فراخواني نمايد. بهترين الگوريتمها براي پردازش بسياري از ساختارهاي اطلاعاتي بصورت بازگشتي ميباشند.
اگر پارامترها روي پشته انتقال يابند، در اين صورت براي هر فراخواني روال مزبور فضاي جديدي براي پارامترهاي آن تخصيص داده ميشود بطوري که آرگومانهاي انتقالي به يک فراخواني روال با آرگومانهاي انتقالي به فراخواني ديگر آن روال اشتباه نميشوند به همين ترتيب، اگر مقادير پشته ذخيره ميشوند، در اين صورت ميتوان از همان ثباتها و يا حتي مکانهاي حافظه در هر فراخواني بازگشتي يک روال استفاده نمود.
بدنه يك روال دستورالعملهاي call , return در این حالت آدرس برنامه جاری در stack دخیره میگردد پس از پایان روال و با اجرای دستور ret مقدار قبلی PC از stack بازیابی شده و ادامه برنامه از سر گرفته میشود
دستورالعملهاي push , pop بسیار محتمل است مقادیر رجیسترها در داخل یک روال تغییر کند لذا ذخیره ساری مقادیر اولیه ضروری است برای ذخیره سازی مقادیر رجیسترها از دستور push استفاده میشود که این دستور باید در ابتدای روال قرار گیرد برای بازگشت مقادی اولیه به رجیسترها از دستور pop استفاده میشود .این دستورات میباید آخرین دستورات یک روال باشند
انتقال مقادير به يك روال و بالعكس برا یانتقال مقادیر به روال و بر عکس دو روش وجود دارد 1 – استفاده از پشته : که در این حالت مقادیر ارسالی را با استفاده از دستور push به پشته فرستاده و در داخل روال با دستور pop آنرا فراخوانی میکنیم 2 – استفاده از سگمنت داده ای : در این حالت آدرس خاصی از سگمنت را برای انتقال پارامترها در نظر میگیریم و در داخل روال نیز داده ها را از آدرس فوق بازیابی میکنیم
بازگشت پذيري (recursion) یک برنامه recursive برنامه ای است که خود را فراخوانی میکند پیاده سازی یک برنامه خودفراخوان یا بازگشت پذیر در اسمبلی به راحتی نوشتن هر برنامه دیگر است تنها خطر برنامه های خود فراخوان سرریز پشته است زیرا در هر فراخوانی یکبار مقدار pc در پشته ذخیره میگردد
فصل هفتم عمليات رشته ها
مطالب اين فصل استفاده از دستورالعملهاي رشته اي پيشوندهاي تكرار و بقيه دستورالعملهاي رشته اي ترجمه كاراكترها تبديل يك عدد مكمل 2 به يك رشته اسكي
استفاده از دستورالعملهاي رشتهاي پنج دستورالعمل وجود دارد که براي عمليات بر روي رشتهها طراحي شدهاند: Movs : براي کپيکردن يک رشته از يک موقعيت حافظه به موقعيت ديگر Cmps: براي مقايسه محتويات دو رشته Scas: ميتوان در يک رشته به دنبال يک مقدار معين گشت. Stos : ميتواند براي ذخيره کردن يک مقدار جديد در يک رشته به کار برود. Lods: يک مقدار را از يک رشته به دست ميآورد.
رشته به مجموعهاي متوالي از بايتها يا کلمات در حافظه اشاره ميکند. معمولاً در يک برنامه رشتهها به وسيله دستورات اسمبلر زير در سگمنت داده تعريف ميشوند: Response DB 80 Dup(?) Label_1 DB 'the results are',0 Word_string DW 50 Dup (?) هر دستورالعمل رشتهاي روي يک رشته منبع، يک رشته مقصد يا هر دو عمل ميکند.
براي مشخص کردن هر بايت يا هر کلمه از روش آدرسدهي غيرمستقيم ثبات استفاده ميگردد. اين دستورالعملها براي دستيابي عناصر رشته مبدأ از آفستي که در ثبات SI قرار دارد و براي دستيابي عناصر رشته مقصد از آفستي که در ثبات DI قرار دارد، استفاده ميکنند. عنصر مبدأ در سگمنت داده قرار دارد بنابراين آدرس واقعي آن عبارت از DS:SI ميباشد. عنصر مقصد در سگمنت فوقالعاده قرار دارد، بنابراين آدرس واقعي آن عبارت از ES:DI ميباشد.
از آنجايي که آدرسهاي عناصر رشتهاي مبدأ و مقصد هميشه در ثباتهاي SI و DI قرار دارند، براي مشخص کردن اين آدرسها به هيچ عملوندي نياز نميباشد. در اين صورت اسمبلر اندازه عناصري را که بايد مورد استفاده قرار بگيرند نميداند.
ماکرو اسمبلر شرکت مايکروسافت براي حل اين مشکل دو راه پيشنهاد ميکند: از عملوندهاي مقصد و منبع استفاده شود. از فرمهاي خاصي از دستور که اندازه عنصر را تعيين ميکنند، استفاده نمود.
وقتي عناصر در اندازه بايت مورد استفاده قرار ميگيرند، ثباتهاي DI و SI (شاخص) فقط يک واحد تغيير داده ميشوند ولي وقتي که عناصر در اندازه کلمه مورد استفاده قرار ميگيرند، ثباتهاي SI و DI به اندازه دو واحد تغيير ميکنند.
جهت حرکت به وسيله فلگ جهت (DF) که بيت دهم ثبات نشانهها است، تعيين ميشود. اگر فلگ DF حاوي مقدار يک باشد، آنگاه مقادير SI و DI به وسيله دستورالعملهاي رشتهاي کاهش داده ميشوند. بنابراين جهت رشته از سمت راست به چپ است. اگر فلگ DF حاوي مقدار صفر باشد، آنگاه مقادير SI و DI به وسيله دستورالعملهاي رشتهاي افزايش داده ميشوند. بنابراين دو رشته از چپ به راست مورد پردازش قرار ميگيرند.
دستور cld فلگ DF را صفر ميکند؛ دستور ctd فلگ DF را يک ميکند. دستورالعمل انتقال رشته يعني MOVS يک عنصر رشته (بايت يا کلمه) را از رشته مبدأ به رشته مقصد انتقال مي دهد. دستورالعمل movs بر روي هيچ فلگي اثر نميگذارد.
قبل از استفاده از movs، بسياري مراحل مقدماتي بايد انجام شوند: ثبات سگمنت فوقالعاده ES بايد حاوي شماره سگمنت رشته مقصد باشد. ثباتهاي DI و SI بايد به آفست اولين بايت رشتهاي که بايد مورد پردازش قرار گيرند، مقداردهي گردند. ثبات نشانهها بايد به مقدار مناسب، مقداردهي شود.
براي آنکه بدانيم آيا بايت بعدي مبدأ همان کاراکتر تهي است، دستور زير مورد استفاده قرار ميگيرد: While: cmp BYTE PTR [Si],0 ;null source byte? فرم [Si] نشاندهنده آن است که آدرسدهي غيرمستقيم ثبات مورد استفاده قرار گرفته است، بنابراين عنصري که در آفست SI قرار دارد، مورد استفاده قرار ميگيرد و اين همان بايت جاري رشته مبدأ است.
پيشوندهاي تکرار: پيشوند rep معمولاً با دستورالعمل movs و دستورالعمل Stos به کار ميرود. اين پيشوند باعث ميشود که طرح زير اجرا شود: while (CX شماره موجود در ≠ صفر) loop دستورالعمل اوليه را اجرا کن; کم کن CX يک واحد از; End while;
دو پيشوند تکرار ديگر عبارتند از repe و repne. فرم repe به معني «تا زماني که حالت تساوي وجود دارد، تکرار کن» و فرم repz يعني «تا زماني که صفر است تکرار کن» ميباشد. به همين ترتيب repne و repnzبه معني «تا زماني که حالت مساوي وجود ندارد تکرار کن» و «تا زماني که صفر نيست تکرار کن» ميباشد. هر کدام از اين پيشوندهاي تکرار مناسب استفاده با دو دستورالعمل رشتهاي cmps و scas که بر روي فلگ صفر اثر ميکنند، ميباشند.
اين پيشوندها تا زماني که CX صفر نيست، دستورالعمل اوليه را تکرار ميکنند. پيشوندهاي repe و repz تکرار را تا زماني که ZF=1است تکرار ميکنند. پيشوندهاي repne و repnz تکرار را تا زماني که ZF=0 است تکرار ميکنند.
Cmps دو عنصر رشتهاي را تفريق کرده و فلگها را بر اساس آنها تنظيم ميکند؛ هيچکدام از عملوندها تغيير داده نميشوند. چنانچه به وسيله دستور cmps بخواهيم بدانيم که دو رشته مشابه هستند، پيشوند repe براي همراهي با اين دستورالعمل کاملاً مناسب است. اغلب لازم است رشتهاي که در درون رشته ديگري قرار دارد، جستجو کرد.
تست مقابل براي تطبيق ميتواند صورت بگيرد SI:= آدرس رشته موردنظر; DI:= آدرس رشته مقصد+POSITION-1; CX:=طول رشته موردنظر; Forever loop If CX=0 then از حلقه خارج شو; end if; را تنظيم کن ZF را مقايسه کن و متناسب با آن [DI] و [SI] را افزايش بده SI; را افزايش بده DI; را کاهش بده CX; If ZF=0 then از حلقه خارج شود; enf if; End loop; If ZF-1 Then رشته موردنظر پيدا شد; End if; تست مقابل براي تطبيق ميتواند صورت بگيرد
دليل وجود ifاضافي در انتهاي طرح آن است که: از آنجايي که حلقه وقتي تمام ميشود که CX=0 بوده و يا زماني که ZF=0 باشد، لازم است اطمينان حاصل نمود که آخرين جفت کاراکترهاي مقايسه شده يکسان بودهاند.
دستورالعمل پويش رشتهاي scas براي پويش يک رشته جهت وجود داشتن و يا وجود نداشتن يک عنصر رشتهاي معين به کار ميرود. فرمهاي scasb و scasw از هيچ عملوندي استفاده نميکنند زيرا فرم دستور اندازه عنصر موردنظر را تعيين مينمايد.
دستورالعمل ذخيرهسازي رشتهاي stos يک بايت يا يک کلمه را از ثبات AL يا رشته AX به يک عنصر رشته مقصد کپي مينمايد. اين دستور بر روي هيچ فلگي اثر نميگذارد. بنابراين وقتي که اين دستورالعمل با پيشوند rep تکرار شود، يک مقدار را در موقعيتهاي متوالي يک رشته کپي مينمايد. دستورالعمل بار کردن رشتهاي lods يک عنصر رشته مبدأ را به ثبات AL يا ثبات AX بار مينمايد. دستورالعمل lods بر روي فلگها هيچ اثري نميگذارد.
ترجمه کاراکترها دستورالعمل Xlat يک کاراکتر را به کاراکتر ديگري ترجمه مينمايد. اين دستورالعمل در ترکيب با دستورالعملهاي پردازش رشته به راحتي ميتواند تمام کاراکترهاي يک رشته را ترجمه کند. قبل از اجراي دستورالعمل Xlat، کاراکتري که بايد ترجمه شود در ثبات AL قرار داده ميشود. اين دستورالعمل براي ترجمه بايتي که در آن AL قرار دارد از يک جدول ترجمه که در سگمنت داده قرار دارد استفاده ميکند.
به طور کلي Xlat از کاراکتري که ترجمه ميگردد بعنوان آفست در جدول ترجمه استفاده مينمايد و بايتي را که در آفست مزبور قرار دارد جايگزين آن ميکند. دستورالعمل Xlat داراي دو فرم زير است: Xlat و Xlat table_name در فرم دوم، عملوند table_nameبايد جدول ترجمه را آدرسدهي نمايد. البته استفاده از اين عملوند به طور خودکار ثبات BX را مقداردهي نمينمايد. اين عملوند ميتواند حذف گردد مگر در موارد نادري که نياز به پيشوند اعلام صريح ثبات سگمنت وجود داشته باشد.
ترجمه يک کاراکتر به خودش مجاز است. همين اتفاق براي ارقام عددي ميافتد ترجمه يک کاراکتر به خودش مجاز است. همين اتفاق براي ارقام عددي ميافتد. کدهاي اسکي 3016 تا 3916 که معرف اعداد صفر تا 9 هستند در آفستهاي 3016 تا 3916 قرار گرفتهاند. کدهاي هفت کاراکتر : تا @ کاراکترهاي بعدي جدول اسکي هستند، هرکدام از آنها به يک فاصله خالي ترجمه خواهند شد.
تبديل يک عدد مکمل دو به يک رشته اسکي ماکروي itoa براي تبديل يک عدد صحيح مکمل دو به يک رشته شش کاراکتري جهت خروجي، مورد استفاده قرار گرفته است. اين دستورالعملها براي ارسال پارامترها به روال itoa_proc از ثباتهاي AX و DI استفاده مينمايند. بنابراين کاربر نبايد نگران دست خوردن هيچکدام از ثباتها باشد. ثباتهاي AX و DI ابتدا در پشته ذخيره شده و در انتهاي برنامه بازيابي ميشوند. عدد مکمل دو که در source قرار دارد در ثبات AX و آدرس مقصد جهت رشته در ثبات DI قرار داده ميشود.
استفاده از دستورالعملهاي رشته اي در زبان اسمبلی 5 دستورالعمل رشته ای وجود دارد انتقال رشته ها MOVS مقایسه رشته ها CMPS پویش رشته ها SCAS ذخیره رشته ها STOS بارگذاری رشته ها LODS
پيشوندهاي تكرار و بقيه دستورالعملهاي رشته اي در زبان اسمبلی 3 پیشوند تکرار دستورالعملهای رشته وجود دارد تکرار انتقال یا ذخیره سازی آرایه REP ( MOVS STOS) تکرار تا وجود حالت تساوی repz repe تکرار تا شرط عدم وجود حالت تساوی repnz repne شرط تکرار پیشوند CX <> 0 REP CX <> 0 and ZF=1 REPE REPZ CX <> 0 and ZF=0 REPNZ REPNE
ترجمه كاراكترها کارکترها در فرمهای نمایش متفوتی نشانداده میشوند فرم ebcdic یک عد یک عدد 7 بیتی است که توان نمایش 128 کاراکتر را دارد فرم ascii یک عدد یک بایتی برای نمایش 256 کارکتر را دارد دستور xlat در زبان اسمبلی برای ترجمه کارکترها مورد استفاده قرار میگیرد
تبديل يك عدد مكمل 2 به يك رشته اسكي در زبان اسمبلی ماکروی itoa برا ی این تبدیل در نظر گرفته شده است استفاده از این ماکرو به این دلیل ضرورت دارد که همواره اعدادی که از صفحه کلید دریافت میشوند بصورت کارکتر بوده و برای ذخیره در رجیسترها باید بصورت عدد مکمل 2 در آیند
فصل هشتم ساير حالتهاي آدرس دهي
مطالب اين فصل حالتهاي آدرس دهي دستيابي غير پياپي عناصر يك آرايه ساختارها
حالتهای آدرس دهی به اختصار در شکل زیر آمده است حالتهاي آدرس دهي حالتهای آدرس دهی به اختصار در شکل زیر آمده است بلاواسطه ثبات حافظه مستقیم غیر مستقیم ثبات غیر مستقیم دارای مبنا دارای اندیس دارای مبنا و اندیس
حالتهاي آدرسدهي عملوندهاي دستورالعملها، به سه گروه عمده تقسيم ميشوند. بلاواسطه ثبات حافظه
بلاواسطه: مقاديري هستند که در داخل دستورالعملها قرار ميگيرند. ثبات: شامل مقاديري هستند که از يک ثبات برداشته شده و يا نتيجه دستورالعمل در يک ثبات مقصد قرار ميگيرد. حافظه: به دو گروه مستقيم و غيرمستقيم تقسيم ميشوند.
از آدرسدهي حافظه، احتمالاً حالت مستقيم بيشترين مورد استفاده را دارد. در برنامه منبع، اسمبلر مايکروسافت براي متمايز کردن يک عملوند غيرمستقيم از انواع ديگر عملوندها وجود حداقل يک نام ثبات در داخل کروشه را لازم ميداند.
به عنوان مثال، [bx] يک عملوند حافظه غيرمستقيم را نشان ميدهد، در صورتي که bx يک عملوند ثبات ميباشد. حالت ثبات غيرمستقيم سادهترين حالت غيرمستقيم ميباشد. براي حالت ثبات غيرمستقيم تنها چهار قالب کد منبع وجود دارد، يعني [bx]، [si]، [dx]، [bp]، باين معني که تنها ميتوان از چهار ثبات BX، SI، DI و BP براي آدرسدهي ثبات غيرمستقيم استفاده کرده و نميتوان مقدار ديگري را به همراه اين ثباتها ذکر نمود.
در حالت ثبات غيرمستقيم، سه ثبات BX، SI و DI افست دادهها در سگمنت دادهها را نگهداري ميکنند. به عنوان مثال: عملوند [SI] در آدرس DS:SIقرار دارد که ثبات DS شامل شماره سگمنت و ثبات SI شامل افست ميباشد. در آدرسدهي ثبات غيرمستقيم، BP به عملوندهاي واقع در پشته اشاره کرده و سه ثبات ديگر به عملوندهاي واقع در سگمنت دادهها اشاره ميکنند.
ثباتهاي BX و BP را ثباتهاي مبنا و ثباتهاي SI و DI را ثباتهاي انديس ميگويند. عملوندي به صورت [bp+6] يا [bx-4] در حالت مبنا ميباشد. عملوندي به صورت [si+20] يا [di+2] در حالت انديس ميباشد. اين دو حالت خيلي شبيه حالت ثبات غير مستقيم ميباشند. براي به دست آوردن افست عملوند موردنظر، مقدار جابجايي به محتواي ثبات مربوط اضافه ميشود.
زماني که از يک ثبات مبنا و يک ثبات انديس استفاده ميشود، ترکيب BX/Si به اندازه يک سيکل زماني از ترکيب BX/DI سريعتر ميباشد. بهمين ترتيب، ترکيب BP/DI کمي سريعتر از ترکيب BP/SI ميباشد.
دستيابي غيرپياپي عناصر يک آرايه در زبان اسمبلي، حافظه لازم براي يک آرايه را ميتوان با رزرو کردن يک بلوک متوالي از حافظه تخصيص داد.
مرتب سازي درجي يکي از سادهترين الگوريتمهاي مرتبسازي ميباشد مرتب سازي درجي يکي از سادهترين الگوريتمهاي مرتبسازي ميباشد. ايده اصلي اين روش اينست که تعداد position-1 عنصر اولي آرايه را به صورت مرتب شده درنظر گرفته و سپس عنصر بعدي را در مکان صحيح خود قرار دارد. اگر اين عمل را براي تمام انديسها تکرار کنيم، يک آرايه مرتب شده نتيجه خواهد شد.
اگر عناصر آرايه داراي ترتيب خاصي نباشد، در اينصورت بايستي از جستجوي پياپي استفاده نمود؛ از عنصر اول شروع کرده و عناصر آرايه را يکي يکي امتحان ميکنيم. اگر عناصر آرايه مرتب باشند در اين صورت ميتوان از الگوريتم کارآمدتر جستجوي دودويي استفاده نمود.
الگوريتم جستجوي دودويي انديس مياني آرايه را محاسبه کرده و مقدار عنصر مياني آرايه را با کليد جستجو مقايسه ميکند. اگر کليد جستجو برابر مقدار عنصر مياني آرايه باشد در اينصورت الگوريتم جستجو با موفقيت پايان مييابد. اگر کليد جستجو کوچکتر از عنصر مياني آرايه باشد، در اين صورت اگر کليد جستجو در آرايه وجود داشته باشد بايستي در نصف سمت چپي آرايه قرار داشته باشد. اگر کليد جستجو بزرگتر از مقدار عنصر مياني باشد، در اينصورت اگر کليد جستجو در آرايه وجود داشته باشد بايستي در نصف سمت راستي آرايه قرار داشته باشد.
ساختارها يک ساختار مجموعهاي از عناصر داراي انواع مختلف که نام مشترک دارند، ميباشد؛ عناصر يک ساختار را ميتوان با استفاده از نام ساختار و نام فيلد عنصر موردنظر دستيابي نمود.
نوع PartType را ميتوان به صورت زير تعريف نمود: Parttype STRUC PartNbr DW ? Description DB 20 Dup(?) Quantity DW ?
تعريف نوع ساختار هميشه با دستور STRUC شروع شده و با دستور ENDS خاتمه مييابد. مانند زبانهاي سطح بالا، تعريف نوع ساختار هيچ حافظهاي را براي آن تخصيص نميدهد؛ زمان که متغيري ازنوع pARTtYPE تعريف ميشود، حافظه موردنياز براي آن تخصيص داده ميشود.
دستيابي غير پياپي عناصر يك آرايه برای این منظور در زبانهای سطح بالا اندیس آرایه به کار میرود در زبان اسمبلی میباید آرایه را در مکان متوالی ذخیره نماییم تا بتوانیم دسترسی غیر پیاپی به آن داشته باشیم در این حالت با محاسبه اندیس در طول آرایه و محاسبه offset میتوانیم به المان مورد نظر در آرایه دسترسی داشته باشیم
ساختارها ساختار مجموعه ای از عناصر است با انواع داده ها با نام مشترک عناصر یک ساختار را میتوان با نام مشترک و نام فیلد دستیابی کرد در پاسکال به این ساحتار فیلد گفته میشود میکرو اسمبلر نیز دستور field را برای تعریف ساختار در نظر گرفته است
فصل نهم دستكاري بيتها
مطالب اين فصل عمليات منطقي دستورالعملهاي شيفت و دوران تبديل يك رشته اسكي به يك عدد صحيح مكمل 2
عمليات منطقي در زبان اسمبلي مقدار بولي true با مقدار بيتي يک و مقدار بولي false با مقدار بولي صفر مشخص ميشود. تنها تفاوت بين or و xor آن است که در or، حاصل 1 or 1 يک، ولي در xor حاصل 1 xor 1 صفر ميباشد. به عبارت ديگر دستورالعمل xor بدين معني است که وقتي يکي از طرفين برابر يک باشد، خروجي برابر يک است ولي نه زماني که هر دو طرف برابر يک هستند.
دستورالعملهاي and، or، xor و not عمليات منطقي را پيادهسازي مينمايند
دستورالعمل not هيچ فلگي را تغيير نميدهد دستورالعمل not هيچ فلگي را تغيير نميدهد. ولي ديگر دستورالعملهاي بولي بر روي فلگهاي ZF,SF,PF,OF,CF و AF اثر ميگذارند. فلگ رقم نقلي CF و فلگ سرريزي OF هر دو صفر ميشوند و مقدار فلگ رقم نقلي کمکي ممکن است تغيير کند، اما مقدار آن تعريف نشده است. مقادير فلگهاي توازن (PF)، علامت (SF) و صفر (ZF) بسته به مقدار حاصل عمليات يک يا صفر ميشوند
دستورالعملهاي or , and و xor همگي يکنوع عملوند را قبول ميکنند و براي اجرا به تعداد پالسهاي ساعت يکسان نياز دارند و همينطور تعداد بايتهاي کد هدف آنها برابر است.
بايد توجه داشت که هر بيتي که با 1، and شود، حاصل همان بيت اصلي خواهد بود و از طرف ديگر هر بيتي که با 0، and شود، حاصل صفر خواهد بود. به همين دليل بيتهاي موردنظر در يک بايت يا کلمه ميتوانند به وسيله and شدن با الگويي از بيتها که داراي مقدار 1 در محلهايي که نبايد تغيير کنند و صفر در محلهايي که بايد تغيير کنند، صفر شوند
مقداردهي که معمولاً با دستورالعملهاي منطقي براي تغيير مقدار بيتها به کار ميرود، پوشش (mask)ناميده ميشود. دستورالعمل or براي يک کردن بيتهاي موردنظر در يک بايت يا کلمه بدون تغيير بيتهاي ديگر مفيد است. بايد توجه داشت که اگر مقدار 1 با 0 يا 1 ديگر or شود، آنگاه حاصل 1 خواهد بود ولي اگر يکي از عملوندهاي 0 باشد، آنگاه نتيجه عمل or همان مقدار عملوند ديگر خواهد بود.
دستورالعمل xor بيتهاي موردنظر يک بايت يا يک کلمه را بدون تغيير بيتهاي ديگر معکوس ميکند. دليل اين امر اين است که 0 xor 1 مساوي 1 بوده و 1xor1 مساوي 0است. اين بدان معني است که هر بيتي را که به وسيله دستورالعمل xor با بيت 1 ترکيب کنيم حاصل معکوس بيت اوليه خواهد بود. اگر بايتي که در flags قرار دارد براي ذخيره کردن هشت مقدار بولي مورد استفاده قرار گرفته باشد، آنگاه دستورالعمل or ميتوان مقادير (true) 1 را به هر بيت موردنظري نسبت دهد.
کاربردهاي ديگر دستورالعملهاي منطقي انجام عمليات مشخص رياضي به جاي دستورالعملهاي رياضي دستکاري کدهاي اسکي تبديل يک عدد صحيح بين 0 نا 9 به کد اسکي متناظر آن توسط دستورالعمل or تبديل حروف کوچک و حروف بزرگ الفبا در جدول اسکي توسط دستورالعمل xor
وظيفه دستورالعمل test آن است که فلگها را تنظيم کند.
دستورالعملهاي شيفت و دوران برنامهنويس به کمک دستورالعملهاي شيفت ودوران ميتواند موقعيت بيتهاي يک کلمه يا بايت را تغيير دهد. دستورالعملهاي شيفت، بيتهاي واقع در موقعيت داده شده به وسيله عملوند مقصد را به طرف چپ يا راست حرکت ميدهند. جهت شيفت ميتواند از آخرين کاراکتر نام دستورالعمل شيفت تشخيص داده شود –Sal و Shl شيفت به طرف چپ هستند، Sar و Shr شيفت به طرف راست ميباشند. شيفتها به دو دسته منطقي و رياضي دستهبندي ميشوند
Shl و Shr شيفتهاي منطقي بوده و Sal و Sar شيفتهاي رياضي ميباشند. چپ راست منطقي رياضي ُShr Shl Sar Sal
فرم کد منبع هر دستورالعمل شيفت به صورت زير ميباشند: S-- تعداد، مقصد براي عملوند تعداد دو نگارش وجود دارد. تک بيتي: S-- مقصد,1 اين نوع دستورالعمل باعث ميشود که فقط يک شيفت در عملوند مقصد صورت گيرد چند بيتي: S-- و مقصد cl در اين فرم، مقدار موجود در ثبات CL به عنوان يک عدد بدون علامت تفسير ميگردد و براي دستور شيفت مشخص ميکند که مقدار موجود در عملوند مقصد را چند بيت شيفت ميدهد.
بيتهايي که از طرف چپ بيرون ميروند بدور ريخته ميشوند بغير از آخرين بيت که در فلگ رقم نقلي CF ذخيره ميگردد. بسته به آخرين مقداري که در عملوند مقصد قرار ميگيرد، فلگهاي علامت (SF)، صفر (ZF) و توازن (PF) تعيين ميگردند. فلگ سرريزي براي يک شيفت چندبيتي تعريف نشده باقي ميماند، اما براي يک شيفت تکبيتي چنانچه بيت علامت حاصل همانند بيت علامت مقدار اوليه عملوند مقصد باشد، برابر صفر شده و چنانچه متفاوت باشند، برابر يک خواهد گرديد. فلگ رقم نقلي کمکي AF تعريف نشده نميباشد.
همانند شيفت به طرف چپ، مقادير SF، ZF و PF به نتيجه عمليات بستگي خواهند داشت و AF تعريف نشده خواهد بود. فلگ سرريزي OFدر يک شيفت چندبيتي تعريف نشده خواهد بود. براي يک شيفت تکبيتي منطقي به طرف راست (Shr)، چنانچه بيت علامت حاصل همانند بيت علامت مقدار اوليه عملوند مقصد باشد، در اينصورت فلگ سرريزي OF برابر صفر شده و در غير اينصورت برابر يک خواهد شد. در شيفت رياضي به طرف راست چندبيتي (Sar)، OF هميشه صفر ميگردد.
دستورالعملهاي شيفت از دستورالعملهاي پايهاي هستند، اما داراي کاربردهاي زيادي ميباشند. وقتي قرار باشد که عددي در دو ضرب شود، يک شيفت تکبيتي به طرف چپ عدد اوليه ميتوان حاصلضرب صحيح را در اختيار بگذارد.
يک شيفت تکبيتي به طرف چپ عملوندهاي علامتدار را نيز دو برابر ميکند. يک عمل شيفت تکبيتي به طرف راست ميتواند به صورت مؤثري براي تقسيم کردن يک عملوند بدون علامت بر دو، مورد استفاده قرار گيرد.
شيفت به طرف راست براي اعداد منفي، به طور کامل همانند تقسيم بر دو نيست. اگر مقسوم يک عدد فرد منفي باشد آنگاه خارج قسمت به صورت نقصاني گرد خواهد شد.
دستورالعملهاي دوران خيلي شبيه دستورالعملهاي شيفت هستند دستورالعملهاي دوران خيلي شبيه دستورالعملهاي شيفت هستند. در دستورالعملهاي شيفت، بيتها از يک طرف شيفت داده شده و به دور ريخته ميشوند، در حاليکه جاهاي خالي از طرف ديگر با صفر پر ميشوند. ولي در دستورالعملهاي دوران، بيتهايي که از يک طرف به بيرون شيفت داده ميشوند، از طرف ديگر فضاهاي خالي را پر ميکنند.
يک دستورالعمل دوران تکبيني داراي فرم زير ميباشند: r-- مقصد,l ;rotate 1 bit چندبيتي: r-- مقصد,CL ;rotate number of bits given by CL در دستورالعملهاي rol (rotate left، دوران به طرف چپ) و ror (rotate right، دوران به طرف راست) ميتوان از عملوندهاي بايت يا کلمه در ثبات يا حافظه استفاده کرد.
آخرين بيت که به طرف ديگر عملوند کپي ميشود در فلگ رقم نقلي CF نيز منعکس ميگردد؛ اين «آخرين بيت» تنها براي دوران حالت تکبيتي ميباشد. فلگ سرريزي OF تنها فلگ ديگري است که از دستورالعملهاي دوران اثر ميپذيرد. در دورانهاي چندبيتي فلگ سرريزي تعريف نشده است.
مثال: بعنوان مثال فرض کنيد ثبات DX حاوي مقدار D25E است و دستورالعمل Rol dx,1 اجرا ميشود، اجرا به صورت دودويي به شکل زير است: و نتيجه در ثبات DX برابر عدد A4BD است. فلگ رقم نقلي برابر يک ميگردد، زيرا يک بيت 1 از انتهاب چپ به طرف راست رفته است.
يک جفت دستورالعمل دوران ديگر وجود دارند که هر کدام به گونهاي عمل ميکنند که فلگ رقم نقلي CF قسمتي از عملوند مقصد است: Rcl , rcr دستورالعملهاي دوران با استفاده از فلگ رقم نقلي که به طور مشخص CF را تغيير ميدهند بر روي OFنيز اثر ميگذارند ولي هيچ تغييري در فلگهاي ديگر نميدهند.
تبديل يک رشته اسکي به يک عدد صحيح مکمل دو ماکروي atoi به منظور پويش ناحيهاي از حافظه که حاوي يک رشته اسکي که نشاندهنده يک عدد صحيح است به کار برده شده است وحاصل آن يک عدد صحيح مکمل دو در ثبات AX است.
اين ماکرو ميتواند به مجموعه دستورالعملهاي زير بسط پيدا کند: Push si ;;save SI Lea si,source ;;source address to SI Call atoi_proc ;;call procedure Pop si ;;restore SI اين دستورالعملها براي ارسال آفست رشته اسکي به روال atoi_proc از ثبات SI استفاده ميکنند. مقدار اوليه ثبات SI در پشته ذخيره ميگردد تا برنامهنويس بتواند از اين ثبات به منظورهاي ديگري استفاده نمايد. شناسه source کاربر و نه اسم source، در ماکروي بسط يافته مورد استفاده قرار ميگيرد.
دستورالعملهاي شيفت و دوران در زبان اسمبلی هر شیفت به منعنای چرخش بیتها درون یک رجیستر است هر چرخش به چپ معادل ضرب در عدد 2 است هر چرخش به راست معادل تقسیم عدد به 2 است عمل دوران باعث میشود بیتی که از یک طرف خارج میشود از سمت دیگر وارد شود دستورات SHL , SHR شیفتهای منطقی هستند دستورات SAL , SAR شیفتهای ریاضی هستند
تبديل يك رشته اسكي به يك عدد صحيح مكمل 2 در زبان اسمبلی ماکروی itoa برا ی این تبدیل در نظر گرفته شده است استفاده از این ماکرو به این دلیل ضرورت دارد که همواره اعدادی که از صفحه کلید دریافت میشوند بصورت کارکتر بوده و برای ذخیره در رجیسترها باید بصورت عدد مکمل 2 در آیند
فصل دهم ساير حالتهاي آدرس دهي
مطالب اين فصل دستورالعملهاي int و جدول بردار وقفه درخواست توابع DOS ورودي / خروجي با دستورات in , out (بدون استفاده از سيستم عامل)
دستورالعمل int و جدول بردار وقفهها بعضي مواقع از فراخواني معمولي روالها استفاده ميشود. ولي DOS و بسياري از سيستمعاملهاي ديگر از نوع بخصوص فراخواني روال استفاده ميکنند؛ يک وقفه نرمافزاري که بعضي مواقع آن را يک تله يا يک استثناء ميگويند.
براي فعال کردن يک وقفه ميتوان از دستورالعمل int استفاده نمود. بعلاوه، بعضي وقفههاي توسط خود سختافزار PC توليد ميشوند.
يک وقفه عملاً داراي يک پردازنده وقفه ميباشد که بلوکي از کد ميباشد که تقريباً مانند يک روال معمولي ميباشد. يک پردازنده وقفه به جاي دستورالعمل Call توسط دستورالعمل int فراخواني ميشود. براي برگشتن از يک پردازنده وقفه، به جاي استفاده از دستورالعمل ret براي يک روال معمولي از دستورالعمل (interrupt return) iret استفاده ميشود.
دستورالعمل Intداراي قالب زير است: Int interrupt_type که Interrupt_typeبرابر يک عدد صحيح از 0 تا 255 ميباشد. وقتي اين دستورالعمل اجرا ميشود، ابتدا محتواي ثبات نشانهها را روي پشته اضافه کرده و سپس نشانههاي IF (نشانه فعالسازي وقفه) و TF (نشانه تله) خاموش ميگردند.
دستورالعمل برگشت از وقفه يعني iret بدون عملوند ميباشد. اين دستورالعمل ابتدا مانند يک دستورالعمل برگشت دور عمل ميکند يعني اينکه ثباتهاي IP و CS را از روي پشته برداشته و سپس مقادي رنشانهها را از روي پشته برميدارد. در نتيجه تمام نشانهها برابر مقاديري که توسط دستورالعمل Int روي پشته ذخيره شده بودند، ميگردد.
معمولاً دستورالعمل into بعد از دستورالعملي که احتمال به وجود آمدن حالت سرريزي وجود داشته باشد، به کار ميرود. بعضي از اين وقفههاي براي پردازش وقفههاي سختافزاري به کار ميروند.
درخواست توابع DOS تمام توابع فراخواني شده توسط int 21h يک پردازنده وقفه معيني را فراخواني ميکنند. تابع مورد نظر با قرار دادن شماره تابع مربوطه در ثبات AH انتخاب ميشود. با توجه به اينکه تمام نشانهها توسط دستورالعملهاي int و iret روي پشته حفظ ميگردند، مقادير نشانهها تغيير پيدا نميکنند.
ورودي/خروجي فايلهاي پياپي با استفاده از DOS اکثر توابع DOS که از طريق int 21h فراخواني ميشوند، در مورد عمليات روي فايلهاي ديسک ميباشند. از جمله توابع زير ميباشند. تشکيل دادن يک فايل جديد باز کردن يک فايل بستن يک فايل خواندن داده از يک فايل نوشتن داده روي يک فايل حذف کردن يک فايل
براي شناسايي يک فايل، اکثر توابع DOS از يک عدد 16 بيتي به نام هندل فايل استفاده ميکنند. در زمان باز کردن يک فايل، نام به سيستم DOS انتقال يافته و هندل فايل مزبور براي استفادههاي آتي توسط DOS برگردانده ميشود. براي خواندن از فايل، نوشتن روي يک فايل يا بستن يک فايل، هندل فايل موردنظر به سيستم DOS انتقال مييابد.
ثبات AL شامل اطلاعاتي در مورد نحوه باز کردن فايل موردنظر ميباشد: چهار بيت پائيني شامل يک عدد بدون علامت به شرح زير ميباشد. 0000 براي باز کردن فايل به صورت فقط خواندن 0001 براي باز کردن فايل به صورت فقط نوشتن 0010 براي باز کردن فايل به صورت خواندن و نوشتن
براي يک محيط ساده PC، ميتوان ثبات AL را به صورت زير مقداردهي کرد: 0 براي خواندن از فايل 1 براي نوشتن روي فايل 2 براي خواندن و نوشتن فايل
کدهاي خطا: کدهايي براي وجود داشتن يک مقدار نادرست در ثابت AL وجود نداشتن يک فايل تعداد فايلهاي باز بيش از اندازه مجاز بودن
ورودي/خروجي بدون سيستمعامل (با استفاده از دستورالعملهاي int و out) در اين دور مورد استفاده از روالها و توابع DOS براي انجام عمليات ورودي و خروجي تأکيد شده است. باين ترتيب برنامهها ميتوانند از يک سيستم کامپيوتري به سيستم ديگري تا اندازهاي قابل حمل باشند با وجود اين، در پائينترين سطح اجرا، ورودي و خروجي بايستي با استفاده از دستورالعملهاي Inو out صورت گيرد. منبع دستورالعمل out بايستي ثبات AX (يک کلمه) يا AL (يک بايت) باشد. بهمين ترتيب، مقصد دستورالعمل in بايستي برابر ثبات AX يا AL باشد.
از درگاه کنترل چاپگر براي هدايت عمليات مختلف چاپگر استفاده ميشود. بيت 0 معمولاً برابربا 0 ميباشد. ولي براي مطلع ساختن چاپگر از اينکه يک بايت داده با آن ارسال شده است، اين بيت براي مدت زمان کوتاهي برابر 1 قرار داده ميشود.
قبل از فرستادن يک کاراکتر به چاپگر، برنامه بايستي اطمينان حاصل کند که چاپگر مشغول نميباشد. اينکار با خواندن يک بايت از درگاه وضعيت چاپگر و کنترل بيت 7 وضعيت را نشان ميأهد، صورت ميگيرد. اين عمل تا زماني که اين بيت برابر 0 ميباشد تکرار ميگردد. به محض آزاد شدن چاپگر، کاراکتر موردنظر در داخل ثبات AL و آدرس درگاه دادهها در داخل ثبات DXقرار گرفته و دستورالعمل out بايت مربوط را ارسال ميکند.
يک PC همچنين ميتواند از طريق درگاههاي ورودي/خروجي سريال با دستگاههاي جانبي ارتباط برقرار نمايد. تفاوت بين ارتباط موازي و سريال اينست که در ارتباط موازي هشت بيت به طور همزمان از طريق هشت سيم منتقل ميشود، در حالي که در ارتباط سريال، بيتهاي يک بايت باضافه بيتهاي شروع و توقف به صورت يک بيت در هر زمان از طريق يک سيم منتقل ميشوند.
فصل يازدهم پردازش اسمبلي
مطالب اين فصل اسمبلي دو گذري كد كردن دستورالعملهاي 8088 دستورات اسمبلر
اسمبلي دوگذري وظيفه يک اسمبلر آن است که کد منبع زبان اسمبلي را به کد هدف تبديل نمايد. مايکرو اسمبلر مايکروسافت يک اسمبلر دوگذري است. اين به آن معني است که يک برنامه منبع زبان اسمبلي دوبار به وسيله MASM پويش ميشود تا فايل کد هدف آن ايجاد شود. ميتوان يک اسمبلر را به صورت يک گذري طرح کرد و بعضي اسمبلرها برنامه منبع را سه بار يا بيشتر پويش ميکنند اما بيشتر اسمبلرها از دو گذر بهره ميبرند.
يک مزيت نوشتن برنامه به زبان اسمبلي نسبت به زبان ماشين آن است که در آن ميتوان از شناسهها يا نمادها براي رجوع به دادهها در سگمنت داده و دستورالعملها در سگمنت کد استفاده نمود. يک وظيفه اسمبلر آن است که يک جدول علائم در ارتباط با هر شناسه با مشخصههاي مختلف را تشکيل داده و آن را حفظ کند.
يک مشخصه برابر نوع يک نماد است. اين انواع شامل موارد زير ميباشد: برچسب دادهها و دستورالعملها نمادهايي که مساوي ثباتها درنظر گرفته شدهاند اسامي روالها اسامي ماکروها اسامي سگمنتها
چنانچه نمادي مربوط به داده يا دستورالعمل باشد، آنگاه موقعيت آن در جدول علائم وارد ميشود. اسمبلر داراي يک شمارنده موقعيت است که اين مقدار را محاسبه ميکند. معمولاً در يک اسمبلر شمارنده موقعيت در ابتداي برنامه يا در ابتداي بخشهاي مهمي از برنامه، صفر ميگردد.
چنانچه اسمبلر بخواهد از اين قاعده پيروي کند که دادهها قبل از دستورالعملهاي اجرايي بايد مشخص باشند، آنگاه جدول علائم وروديهايي را براي دادهها در حين گذر اول در نظر ميگيرد. ممکن است بدين ترتيب به نظر برسد که اسمبلي يک گذري ساده است. البته در چنين مواردي پرش به دستورالعملهاي اجرايي جلوتر با مشکلاتي مواجه خواهد شد. اسمبلرهاي مختلف مقدار کار متفاوتي را در حين گذر اول انجام دهند. بعضي براي ايجاد جدول علائم فقط از شمارنده موقعيت استفاده مينمايند. بعضي ديگر در حين گذر اول هم جدول علائم را ايجاد ميکنند و هم کد هدف تقريباً کاملي را توليد مينمايند. ماکرو اسمبلر مايکروسافت جزء دسته دوم است.
وظيفه اصلي يک اسمبلر، توليد کد هدف است وظيفه اصلي يک اسمبلر، توليد کد هدف است. البته اسمبلرها کارهاي بسيار زياد ديگري را نيز انجام ميدهند. يک وظيفه، ذخيره کردن فضا است. اسمبلر علاوه بر ذخيره کردن حافظه ميتواند فضاي ذخيره شده را با مقادير معيني مقداردهي کند.
اکثر اسمبلرها ميتوانند فايل ليست را توليد کنند، اين فايل کد منبع اصلي را بهمراه کد هدف مربوطه عرضه ميکند. مسئوليت ديگر يک اسمبلر آن است که وقتي اشتباهي در کد منبع وجود دارد پيغامهاي خطا را توليد کند. اسمبلرهاي اوليه فقط براي هر اشتباه فقط شماره خط و کدخطا را نمايش ميدادند. نسلهاي بعدي اسمبلرها يک صفحه مجزا با شماره خط و پيغام خطا ايجاد ميکردند. اکثر اسمبلرها ميتوانند پيغام خطا را در فايل ليست در محلي که خطا وجود دارد قرار دهند. ماکرو اسمبلر مايکروسافت پيغام خطا را در فايل ليست قرار ميدهد و آنها را برروي صفحه نمايش نيز نمايش ميدهد.
علاوه بر ليستي که برنامه منبع و کد هدف را نشان ميدهد، اغلب اسمبلرها ميتوانند ليست علائم مورد استفاده در برنامه را نيز توليد نمايند. چنين ليستي ممکن است اطلاعاتي را درباره مشخصه هر نماد و همينطور جدول ارجاع را که مشخص کننده خطي است که يک نماد در آنجا تعريف شده است و خطوطي که به آن رجوع کردهاند، در برگيرد.
ماکرو اسمبلر مايکروسافت يک اسمبل دوگذري است ماکرو اسمبلر مايکروسافت يک اسمبل دوگذري است. اين اسمبلر قادر است کدهاي هدفي را ايجاد کند که به محلهايي در فايلهاي ديگر رجوع نمايند و همينطور حاوي علائمي باشد که قابل جابجايي ميباشند. برنامه کمکي LINK در MS-DOS فايلهايي را که داراي کدهاي هدف مجزا هستند دريکديگر ترکيب کرده و رجوع به فايلهاي ديگر را ممکن ميسازد. لودر MS-DOS که به طور خودکار با وارد کردن اسم فايل برنامه اجرايي صدا ميشود، قسمت نهايي کار ترجمه فايل را انجام ميدهد، يعني قبل از آمادهسازي اجرا آن را در درون حافظه بار ميکند.
چند دستور اسمبلر هر کدام از دستورات اسمبلر از اسمبلر ميخواهد که وظيفه خاصي را انجام دهد. دستور اسمبلر ASSUMEداراي فرم زير است: ASSUME segment_register:segment_name,… که segment_name ميتوان هرکدام از ثباتها ES,DS,CS يا SS بوده و SEGMENT_NAMEبرچسب دستور اسمبلر SEGMENTاست.
چنانچه MASM به علامتي برخورد نمايد که در سگمنتي که اسم آن در دستور اسمبلر ASSUME معرفي شده است، وجود نداشته بشاد، آنگاه اسمبلر يک پيغام خطا توليد خواهد نمود. يک برنامه کد منبع زبان اسمبلي ممکن است داراي چندين دستور اسمبلر ASSUME باشد. اين مطلب بخصوص در مورد برنامههاي طولاني که حاوي روالهاي بسياري هستند صحيح است. همانطور که دستورات پويش ميشوند، اسمبلر از جديدترين اطلاعاتي که به ثبات سگمنت نسبت داده شده است، استفاده ميکند.
گاهي اوقات لازم است که از MASM خواسته شود که از فرض قبلي در مورد ثبات سگمنت صرفنظر کند و هيچ فرض جديدي هم در نظر گرفته نشود، در چنين حالتي ميتوان از دستور اسمبلر ASSUME به صورت زير استفاده نمود: Segment_register: NOTHING
يک اسمبلر به طور معمول شمارنده موقعيت را از ابتداي هر سگمنت از صفر شورع کرده و آن را به تعداد بايتهاي لازم براي هر دستورالعمل افزايش ميدهد. ميتوان از اسمبلر خواست که براي مقدار ابتدايي شمارنده موقعيت، مقدار خاصي را درنظر بگيرد. MASM و بسياري از اسمبلرهاي ديگر براي اين منظور از دستور اسمبلر Org استفاده مينمايند. شکل کلي اين دستور اسمبلر به صورت زير است: ORG value که در آن value يک آفست را مشخص ميکند. وقتي MASM به دستور اسمبلر ORG برخورد مينمايد، شمارنده موقعيت را با مقدار مشخص شده پرمينمايد.
MASM دستورات اسمبلر EVEN و ALIGN را عرضه ميکند، اين دستورات اسمبلر بر روي شمارنده موقعيت اثر ميگذارند. معمولاً دستور اسمبلر EVEN همراه با دستور اسمبلر DW به کار ميرود تا يک کلمه را تعريف نمايد. اگر شمارنده موقعيت زودج باشد دستور اسمبلر EVEN هيچ اثري نخواهد داشت ولي اگر شمارنده موقعيت فرد باشد، MASM يک دستورالعمل nop (بايت تکي برابر 90) را درج ميکند تا شمارنده موقعيت در زمان اسمبل شدن DW زوج باشد.
هر فايل منبع ميتواند داراي يک دستور اسمبلر TITLE باشد TITLE text که در آن text هر رشتهاي از کاراکترها تا حداکثر 60 کاراکتر است. رشتهاي که به وسيله اين دستور اسمبلر مشخص ميشود در دومين خط هر صفحه از فايل ليست اسمبلي نوشته ميشود.
فصل دوازدهم ماكروها و اسمبلي شرطي
مطالب اين فصل تعريف و بسط ماكروها اسمبلي شرطي ماكروهاي IO.H
تعريف و بسط دادن ماکروها اسمبلر يک ماکرو را به دستورالعملهاي تشکيل دهنده ماکروي مزبور بسط داده و سپس اين دستورالعملهاي جديد را اسمبل ميکند.
تعريف يک ماکرو شبيه تعريف يک روال در يک زبان سطح بالا ميباشد. خط اول، نام ماکروي موردنظر و ليست پارامترها را ذکر ميکند؛ قسمت اصلي تعريف يک ماکرو متشکل از دستورالعملهايي است که طرز عمل ماکروي مربوط را برحسب پارامترهاي آن بيان ميکند. يک ماکرو همچنين مانند يک روال زبانهاي سطح بالا فراخواني ميشود. نام ماکروي موردنظر و به دنبال آن ليست آرگومانها ذکر ميگردد.
تفاوت روال و ماکرو: فراخواني يک روال در يک زبان سطح بالا به تعدادي دستورالعملهاي مربوط به انتقال دادن آرگومانهاي ذکر شده در دستورالعمل call، کامپايل ميشود. فراخواني يک ماکرو عملاً به دستورالعملهاي داده شده در تعريف ماکروي مزبور بسط داده شده و آرگومانها جايگزين پارامترهاي استفاده شده در تعريف ماکروي مربوط ميگردد. کد يک ماکرو با هر بار فراخواني آن تکرار ميشود، اما تنها يک نسخه از کد يک روال وجود دارد. با توجه به اينکه هيچگونه بالا سري براي انتقال دادن پارامترها يا براي دستورالعملهاي call و ret وجود ندارد، معمولاً ماکروها سريعتر از فراخواني روالها اجرا ميشوند ولي اين معمولاً به بهاي طولاني تر شدن کد هدف در مورد فراخواني ماکروها، صورت ميگيرد.
تعريف يک ماکرو در بين دستورات MACRO و ENDM قرار داده ميشود. شکل تعريف يک ماکرو به صورت زير ميباشد. نام MACRO ليست پارامترها دستورالعملهاي زبان اسمبلي ENDM تعريف يک ماکرو ميتواند در هر جاي برنامه اسمبلي ذکر شود به شرط اينکه اين تعريف قبل از فراخوانيهاي آن بيايد.
اسمبلي شرطي مواردي که مورد استفاده ميتواند قرار بگيرد: مواقعي که برنامهنويس ميخواهد که اشکال نسبتاً متفاوتي از يک برنامه يا يک روال را توليد نمايد. زماني که برنامهنويس بخواهد در سطح زبان ماشين عمليات ورودي يا خروجي را انجام دهد که تنها آدرس درگاههاي مورد استفاده در ماشينهاي مختلف تغيير کند. زماني که بسط يک ماکرو برحسب تعداد و نوع آرگومانها تغيير پيدا ميکند.
دستور %OUT به MASM ميگويد که يک پيغامي را روي دستگاه خروجي استاندارد که معمولاً صفحه نمايش ميباشد، چاپ نمايد: %OUT message که message ميتواند مجموعهاي از کاراکترها از جمله کاراکتر خالي و علائم املايي باشد. استفاده از دستور %outمنحصر به ماکروها يا اسمبلي شرطي نيست.
ماکروها فايل IO.H ماکروهاي فايل IO.H براي ارائه دستيابي صحيح و آسان به دستگاههاي ورودي و خروجي استاندارد، طراحي شدهاند. دستور XLIST باعث جلوگيري از ليست شدن تمام کد منبع به ويژه محتواي فايل IO.H ميگردد. دستور EXTRN روالهاي خارجي فراخواني شده توسط ماکروها را معرفي ميکند.