ارسلان سفیدگر
ارسلان سفیدگر
خواندن ۵ دقیقه·۴ سال پیش

اسمبلی (پردازنده 8086): چاپ باینری ریجستر

شبیه ساز emu8086
شبیه ساز emu8086

سوال:

برنامه ای بنویسید که اعملیات زیر را انجام دهد و خروجی را به صورت باینری در صفحه نمایش چاپ کند

al = 5
bl = a
al + (bl - 1)

جواب:

برای مقدار دهی و انجام عملیات منطقی چالش خاصی نداریم

MOV al, 5 ; al = 5 MOV bl, 0Ah ; bl = A DEC bl ; bl - 1 ADD al, bl ; al + bl

مقدار al الان عدد 0E هگز است

حالا چالش اصلی نمایش روی صفحه نمایش هست به طور کلی برای چاپ روی صفحه نمایش از اینتراپت 21 به صورت زیر استفاده میکنیم

MOV ah, 2 MOV dl, '1' ; مقداری که میخوایم چاپ بشه، اینجا عدد یک چاپ میشه INT 21H

حالا بیاین منطق ای که من دارم رو بهتون توضیح بدم:

عدد 0E هگز الان در ریجستر al زخیره شده ولی من میخوام باینری اون رو در خروجی نمایش بدم

یعنی خروجی 000001110 باینری، خوب اول بگم من قصد ندارم هگز رو به باینری تبدیل کنم و میخوام یه راه دیگه رو تست کنم، چطور؟ من میام یه ماسک! میزارم به این شکل 1000000 و مقدار ریجستر al با این مقدار مقایسه میکنم و هر دفعه al رو یک واحد به چپ شیفت میدم (دقیقا برعکس این کار رو هم میشه کرد که ماسک رو معکوس کنید و شیفت به راست بکنید ولی نتیجه رو باید برعکس از صفحه نمایش بخونید!)

اینطوری اگه نتیجه and و مقایسه (CMP) من با ماسک یک شد من عدد 1 رو چاپ میکنم و برعکس

بذارید تو کد نشون بدم که قابل فهم تر بشه

MOV bl, al MOV dl, bl SHL bl, 1 AND dl, 10000000b ; AND value of register dl with 80H CMP dl, 10000000b ; Compare value of register dl with 80H ; If dl equal to 80H program will jump to PrintOne section otherwise PrintZero section JE PrintOne PrintZero: ...

اینکه چرا دو خط اول دوبار از al جاهای مختلف کپی کردم رو در ادامه متوجه میشید

بعد کپی گرفتن یک بار شیفت میدم به چپ و بعد AND میکنم که فقط جایگاه ارزش هفتمین بیت رو نگه دارم و بعدش مقایسه میکنم و اگه نتیجه مقایه برابر بود یعنی یک بود پرش میکنم به لیبلی که در ادامه باعث میشه عدد 1 روی صفحه نمایش چاپ بشه در غیر این صورت برنامه ادامه پیدا میکنه به قسمتی که عدد 0 چاپ بشه

و اینم توضیح بدم که بعد کپی کردن al ادامه کد باید در حلقه ای قرار بگیره که 8 بار تکرار بشه چون 8 بیت داریم یعنی 8 بار شیفت بخوره و مقایسه بشه و چاپ بشه...

برای ساخت حلقه من مقدار 8 رو داخل ریجستر cx قرار میدم و هر دفعه یک واحد ازش کم میکنم که وقتی به صفر رسید از برنامه خارج بشم، روی کد بیشتر متوجه میشید:

Loop: MOV dl, bl SHL bl, 1 AND dl, 10000000b ; AND value of register dl with 80H CMP dl, 10000000b ; Compare value of register dl with 80H ; If dl equal to 80H program will jump to PrintOne section otherwise PrintZero section JE PrintOne ; PrintZero: ;PRINT '0' MOV ah, 2 MOV dl, '0' INT 21H DEC cx JCXZ EndLoop ; Check if 8 times passed or not JMP Loop ; Go back to begging of loop PrintOne: ;PRINT '1' MOV ah, 2 MOV dl, '1' INT 21H DEC cx JCXZ EndLoop ; Check if 8 times passed or not JMP Loop ; Go back to begging of loop

همونطور که میبینید بعد اینتراپت 21 که باعث چاپ روی صفحه نمایش میشه من یک واحد از cx کم میکنم و با دستور jcxz که پرش شرطی هست که چک میکنه اگه cx صفر شد انجام بشه و حلقه رو بشکنه

یادتونه دوبار از al کپی گرفتم... چون من دوتا از مقدار رو نیاز دارم ولی از خود al نمیتونم استفاده کنم اگه شما هم متوجه شده باشید اینتراپت 21 از ریجستر ax استفاده میکنه و مقدار من از بین میره :(

کد کامل رو از گیتهاب من میتونید ببینید

تو تصویر بالا صفحه تقریبا مشخصه، اینم خروجی برنامه:

نیومدم دستورات اسمبلی رو یکی یکی معرفی کنم چون الان فکر میکنم کار بیهوده ای هست چون اولا خیلی زیاده دوما خیلی یادگیری انجام نمیده دونستن دستورات و بنظرم اومد حل مثال خیلی بهتره سعی میکنم بازم مثال های دیگه ای رو حل کنم

تامام./

اسمبلیپردازندهبرنامه نویسیریزپردازنده
https://arsalanse.ir
شاید از این پست‌ها خوشتان بیاید