معماری کامپیوتر _ فصل هفتم مانو
به نام خدا
در این مقاله قصد داریم در مورد فصل هفتم معماری کامپیوتر مانو یعنی کنترل ریز برنامه نویسی شده مباحث کلی ای را مطرح کرده و سعی بر این است که تمامی نکات مورد نیاز در این فصل مورد بررسی قرار گیرد.
ابتدا باید خاطر نشان کنم که برای درک بهتر این مقاله بهتر است که مقاله قبلی بنده در مورد فصل پنجم معماری مانو را مورد مطالعه قرار دهید تا مباحث در این فصل برایتان قابل فهم تر باشد.
ابتدا می خواهیم به ساختمان معماری این کامپیوتر بپردازیم و تفاوت های آن را با کامپیوتر پایه را مورد بررسی قرار دهیم و با ارتباطات آن آشنا شویم.
در شکل زیر معماری این کامپیوتر را می بینید :
همانطور که می بینید دیگر خبری از باس داده نیست و اجزای کامپیوتر به طور مستقیم با هم در ارتباط هستند.
در کامپیوتر پایه برای ارتباط یکی از اجزا مقدار خود را بر روی باس قرار میداد و ثبات دیگری آن را دریافت می کرد ( در اکثر موارد ) ولی این جا ارتباطات مستقیم است به همین دلیل دیگر نگران قرار دادن دو مقدار بر روی باس نباشید چون باس وجود ندارد و اینجا صرفا باید مراقب این باشید که دو مقدار بر روی یک سیم قرار نگیرد و البته نکات دیگری که در ادامه گفته خواهد شد.
نکات اصلی این ارتباطات عبارت اند از اینکه تنها ثباتی که می تواند بر روی RAM مقداری بنویسد فقط DR است و تنها ثباتی که پس از READ مقدار در آن قرار می گیرد نیز DR است پس می توان گفت تنها راه ارتباطی ما با RAM ثبات DR می باشد.
ثبات AC همچنان تنها از مدار محاسبه و منطق می تواند مقدار دریافت کند و خروجی آن به DR و مدار محاسبه و منطق ارسال می شود.
نکته دیگر این است که اینجا خبری از ثبات TR نیست یعنی ثبات کمکی وجود ندارد و همه کار ها را باید با استفاده از ثبات های اصلی انجام دهید.
نکته جالب دیگر این است که ثبات IR هم وجود ندارد یعنی ثباتی که در کامپیوتر پایه با استفاده از آن دیکد انجام میشد دیگر وجود ندارد ولی باید گفت که DR اینجا علاوه بر خود , نقش IR را نیز ایفا می کند یعنی دیکد دستورات در DR انجام می شود.
در مورد AR اگر به یاد داشته باشید در کامپیوتر پایه این ثبات از PC و IR ( آدرس ۱۲ بیتی در دیکد ) مقدار دریافت می کرد که اینجا هم به همان شکل است که هم از PC و هم از DR که در اینجا نقش IR را بازی می کند مقدار دریافت می کند.
ثبات PC فقط از AR مقدار دریافت می کند.(برای پرش استفاده می شود)
ثبات DR نیز از PC و RAM و AC مقدار دریافت می کند که MUX بالای آن برای انتخاب یکی از آن ها می باشد.
نکات تکراری نیز این است که تنها ثباتی که می تواند به RAM ادرس بدهد AR است.
AR آدرس RAM برای نوشتن یا خواندن را مشخص می کند.
PC آدرس دستور بعدی را در خود دارد.
نکته دیگر اینکه RAM در اینجا ۲۰۴۸ * ۱۶ می باشد , طبق نکته فصل قبل می توان فهمید ثبات هایی که با داده ی RAM سر و کار دارند باید ۱۶ بیتی باشند و ثبات هایی که با آدرس RAM کار می کنند باید ۱۱ بیتی ( ۲۰۴۸ = ۲۱۱ ) باشند پس AR , PC ثبات های ۱۱ بیتی و DR , AC ثبات های ۱۶ بیتی ما هستند.
از طرفی برای دیکد کردن از آن جایی که آدرس در کامپیوتر پایه ۱۲ بیتی در دیکد ۱۲ بیت از IR به آدرس اختصاص میافت اما اینجا آدرس ۱۱ بیتی است پس ۱۱ بیت از DR ( که جای IR را پر کرده است ) به آدرس اختصاص میابد.
حال با کم شدن یه بیت از بیت های آدرس به بیت های OPCODE یک بیت اضافه می شود پس یعنی اینجا OPCODE , 4 بیتی است.
در شکل زیر نحوه تقسیم بندی DR را برای انجام عمل دیکد و همچنین ۴ مورد از دستورات آن را می بینید :
نکته اصلی و فرق اساسی این کامپیوتر با کامپیوتر پایه در این است که در اینجا حافظه کنترل در واحد کنترل , یا همان ROM وجود دارد.
حال سوال این است که ROM چه کاری برای ما انجام میدهد؟
اول اینکه ROM , 128 * 20 است یعنی ۱۲۸ سطر دارد که هر سطر آن ۲۰ خانه دارد و همانند RAM یک ثبات دارد که به خانه های آن آدرس می دهد که نام آن CAR است و بدیهی است که برای ۱۲۸ خط نیاز به ۷ بیت ( ۱۲۸ = ۲۷ ) می باشد پس CAR , 7 بیتی است.
جواب سوال اینجاست که دستورات در RAM قرار دارند یعنی ما در RAM می گوییم عمل ADD را انجام بده اما اینکه چگونه عمل ADD پیاده سازی و اجرا شده است در RAM چیزی وجود ندارد بلکه پیاده سازی آن در ROM است.
یعنی ما در RAM میگوییم عمل ADD را انجام بده سپس برنامه به ROM رفته و ریز دستورات عمل ADD را می گیرد و اجرا می کند.
اینکه ارتباط RAM و ROM چگونه برقرار می شود به این صورت است که برای پیدا کردن دستورات RAM در ROM ابتدا OPCODE دستورات که ۴ بیتی می باشند را برداشته و از آن برای پیدا کردن دستور مورد نظر در ROM استفاده می کنیم و این یک قرار داد از قبل تعیین شده در این کامپیوتر است که هر تابع ای که در RAM فراخوانی می شود همانند ADD باید در ROM در یک آدرس از پیش تعیین شده قرار داشته باشد و تعداد خط هایی که برای پیاده سازی آن مورد استفاده قرار می گیرد باید ۴ خط متوالی باشند که یعنی اگر به خط کمتری نیاز بود باقی خط ها خالی می مانند و اگر به تعداد خط های بیشتری نیاز بود در ادامه آن نوشته نمی شود بلکه در یک مکان خالی خط های ۵ به بعد نوشته می شوند که خلاصه بخواهم بگویم اینکه بین RAM و ROM قراردادی است که هر تابع باید در خط خاصی قرار داشته باشد.
آن خط خاص چیست؟
برای مثال دستور BRANCH که OPCODE آن برابر ۰۰۰۱ است آدرس این تابع در ROM برابر ۰۰۰۰۱۰۰ است.
یعنی OPCODE را می گیرد یک ۰ به سمت چپ و دو ۰ به سمت راست آن اضافه می کند.
این عمل OPCODE را به آدرس orginal در ROM تبدیل می کند که به این عمل به اصطلاح MAPPING می گویند یعنی نگاشت آدرس به ROM که دلیل دو صفر در راست گذاشتن آن همین ۴ خطی بودن توابع می باشد که با اضافه شدن به OPCODE در عوضش در ,ROM 4 عدد اضافه می شود برای مثال OPCODE تابع ADD برابر ۰۰۰۰ میباشد که آدرس آن در ROM برابر ۰۰۰۰۰۰۰ است , OPCODE تابع BRANCH برابر ۰۰۰۱ میباشد که آدرس آن در ROM برابر ۰۰۰۰۱۰۰ یعنی ۴ است و دستور بعدی یعنی STORE آدرسی برابر ۰۰۰۱۰۰۰ یعنی ۸ دارد که این نشان دهنده قرار داد برای یافتن توابع در ROM میباشد.
پس برای اینکه تابعی یا همان دستوری اجرا شود باید RAM دستور بدهد و پس از عملیات MAPPING و پیدا کردن آدرس آن تابع در ROM این دستور شروع به اجرا کند.
حال می خواهیم ببینیم دستورات چگونه در ROM اجرا می شوند.
هر سطر از ROM برابر با یک خط دستور می باشد که در کامپپیوتر اجرا می شود و همانطور که گفتیم هر خط ROM دارای ۲۰ خانه است که با استفاده از این ۲۰ بیت ما نوع دستورالعمل را مشخص می کنیم.
حال این دستورالعمل ها چیست؟
ما در این کامپیوتر با توجه به نبودن باس می توانیم حداکثر ۳ کار ثباتی را همزمان انجام دهیم.
به شکل زیر که محتوای یه سطر از ROM را به نمایش میگذارد توجه کنید :
F1 , F2 , F3 همان ۳ عملیاتی هستند که انجام می شوند که هر کدام ۳ بیت دارند یعنی هر کدام از این F ها می توانند بیان گر ۸ عمل باشند که در ادامه به عملی که هر کدام از آن ها در قبال ۳ بیتی که دارند انجام می دهند خواهیم پرداخت.
از طرفی هر خط از دستور در ROM نیاز به یک عمل دارد که باید به هر خط بگوییم خط بعدی ای که قرار است اجرا کنی کجاست که BR این کار را با ۲ بیت انجام می دهد.
برای اجرا شدن BR نیاز به یک شرط است که هروقت شرط برقرار بود خطی که BR گفته را انجام بده وگرنه خط بعدی را اجرا کن که این شرط را CD مشخص می کند.
AD هم آدرس جایی است که BR گفته آن را انجام بده.
این توضیحاتی مختصر و غیر کامل بود , لطفا به شکل زیر برای درک بیشتر توجه کنید.
همانطور که در شکل مشاهده می کنید کار هایی که F1 , F2 , F3 به ازای حالت های مختلف انجام می دهند قابل رویت است که ما در هر دستور می توانیم یکی از کار های هر F را انتخاب کنیم یعنی ۳ کار در کل که البته نباید با هم تداخل داشته باشند.
از طرفی باید بدانیم که کدنویسی در این فصل دیگر مثل فصل ۵ نیست بلکه برای انجام هرکاری باید مخفف آن را استفاده کنیم مثلا برای AC <- AC + DR اجرا شود باید از ADD استفاده کنیم که در F1 به آن اشاره شده.
تمامی مخفف ها قابل درک است فقط می توان گفت برای اینکه مثلا AC به DR فرستاده شود باید از مخفف ACTDR استفاده کنیم , برای DR <- M[AR] از RAED استفاده میکنیم , برای M[AR] <- DR از WRITE استفاده میکنیم ( چونRAED , WRITE فقط توسط DR انجام می شود ) , برای NOT کردنه AC از مخفف COM استفاده می شود و … .
در شکل مشخص است که CD به ازای هر حالتی از ۲ بیتی که دارد چه شرطی را ایجاد می کند , اگر ۰۰ باشد که ما از مخفف U استفاده می کنیم یعنی بدون هیچ شرطی کاری که BR میگوید را انجام بده.
اگر ۰۱ باشد که مخفف آن I است یعنی اگر بیت I در DR که مستقیم یا غیر مستقیم بودن آدرس را مشخص می کند اگر این بیت I برابر با ۱ بود عمل BR را انجام بده.
اگر ۱۰ باشد مخفف آن S است یعنی اگر بیت آخر AC یعنی بیت شماره ۱۵ که نشان دهنده ی علامت عدد است , اگر این بیت ۱ بود یعنی اگر AC منفی بود عمل BR را انجام بده.
اگر ۱۱ باشد مخفف آن Z است و یعنی اگر AC کلا ۰ بود عمل BR را انجام بده.
قبل از توضیح BR در مورد JUMP و CALL توضیح می دهم که JUMP یعنی پرش بدونه بازگشت که از یک خطی به خط دیگر پرش انجام می دهید و آن خط را اجرا می کنید اما CALL یعنی همزمان با انچام دادنه پرش آدرس برگشتت را جایی ذخیره کن تا بعد از اجرای این خط جدید بتوانیم به جایی که بودیم برگردیم.
ثباتی به اسم SBR وجود دارد که برای این کار است که وقی دستور CALL می آید آدرس برگشت در SBR ذخیره شود و هنگام بازگشت از آن استفاده شود.
حال ببینیم BR با ۲ بیتی که دارد به ما چه می گوید :
اگر ۰۰ باشد معنا و مخفف آن JUMP می باشد یعنی پرش کن به خطی که در AD آدرسش وجود دارد که این عمل یعنی می خواهیم خط بعدی ای که اجرا می شود خطی باشد که AD نشان می دهد که برای اینکار کافیست AD را به CAR بدهیم اینگونه خط بعدی را ما مشخص کرده ایم البته اگر شرط CD برقرار باشد این اتفاق می افتد وگرنه به خط بعدی می رود یعنی CAR خط بعدی را نشان می دهد و CAR <- CAR +1 می شود.
حال اگر BR برابر ۰۱ باشد مخفف و معنی آن CALL است یعنی همان عمل JUMP را انجام بده با فرق اینکه اگر شرط برقرار بود و خواستین JUMP را انجام بدین قبلش آدرس جایی که باید برگردیم یعنی خط بعدی ای که الان در آن هستیم ( CAR+1 ) را در SBR ذخیره کن , اگر شرط هم برقرار نباشد که به خط بعدی می رود.
اگر BR برابر ۱۰ باشد مخفف و معنی آن RET میباشد که این عمل زمانی انجام میشود که شما CALL کرده باشین حالا تابع اجرایش تمام شده و قصد دارید به جایی که قبلا بودید برگردید , از کجا بدانیم قبلا کجا بودیم؟بله SBR می دونه . چطوری بریم اونجا , فقط کافیه SBR را در CAR یعنی خط بعدی ای که باید اجرا بشه قرار بدیم تا خط بعدی جایی باشه که ما میخواهیم یعنی جایی که قبلا بوده ایم که این عمل بدون شرط اجرا می شود یعنی CD شرط U را برای اجرای آن در نظر می گیرد.( که البته شما می توانید در صورت نیاز از شرط برای اجرای آن نیز استفاده کنید)
اگر BR برابر ۱۱ باشد عملیات MAPPING صورت می گیرد که مخفف آن MAP بوده و توضیحات آن داده شده یعنی در CAR در سمت چپ یک ۰ سپس OPCODE و سپس دو تا ۰ در سمت راست آن قرار میگیرد که این دستور نیز بدون شرط اجرا می شود.
این بود دستوری که در یک خط ROM می شود انجام داد.
حال ببینیم که توابعی مانند ADD , BRANCH , STORE , EXCHANGE چگونه در ROM پیاده سازی می شوند , به شکل زیر توجه کنید :
مهم ترین مباحث می توان گفت همین نوشتن کد در این کامپیوتر است که فعلا قصد دارم کد های بالا را برایتان توضیح دهم و سپس مثال های دیگری را حل می کنیم.
ابتدا در پایین یعنی FETCH باید شروع کنیم , همانند فصل ۵ ابتدا باید دستور را به ثباتی که دستور را دیکد می کند ( اینجا DR ) برسانیم و سپس دیکد کنیم پس اول باید بدانیم کدام دستور را باید بخوانیم , که PC به آن اشاره می کند یعنی کار PC اینه که در هر لحظه به ما بگوید نوبت کدام دستور از RAM است که اجرا شود پس برای اینکه این دستور از RAM را بخوانیم باید این آدرس را به AR برسانیم پس در خط اول می بینید که :
PCTAR U JMP NEXT
یعنی PC را در AR ریخته و سپس بدون هیچ شرطی به خط بعدی برو.
حالا باید این دستور را بخوانیم و در DR قرار بدیم( READ ) برای دیکد و همزمان PC یک عدد اضافه شود و به دستور بعدی اشاره کند :
READ,INCPC U JMP NEXT
حال باید ۱۱ (یازده) بیت آدرس در DR را به AR منتقل کنیم و همزمان عمل MAPPING را انجام دهیم تا از OPCODE دستور برای اجرای آن در ROM استفاده شود :
DRTAR U MAP
پس از اجرای این خط عملیات MAPPING انجام شده و به ROM میرویم و تابع مورد نظر را اجرا می کنیم.
فرض کنید OPCODE برابر ۰۰۰۰ بوده و باید عملیات ADD انجام شود.
در خط اول ADD می بینید که :
NOP I CALL INDRCT
این دستور در مرحله اول همه توابع باید انجام شود ( به جز توابعی که با یک شرط اجرا خواهند شد که بهتر است اول شرط چک شود سپس اگر قرار به اجرا کردنه تابع شد این دستور نوشته شود).
معنی آن این است که بدونه اینکه کار ثباتی ای انجام بدهی و با شرط I یعنی با شرط غیر مستقیم بودن آدرس , تابع INDRCT را CALL کن یعنی پرش کن اجرایش کن سپس برگرد.
تابع INDRCT در زیر FETCH نوشته شده و کارش این است که آدرس غیر مستقیم را به آدرس مستقیم تبدیل می کند, چطوری؟
اینگونه که وقتی آدرس غیر مستقیم است یعنی ما آدرس خانه ای رو داریم که مقدار داخل آن خانه باید آدرس ما باشد ( در فصل ۵ به توضیحات آدرس مستقیم و غیر مستقیم پرداخته ام ) , پس مقدار آن خانه را از RAM میگیریم ( READ ) سپس آن را در AR قرار می دهیم :
READ U JMP NEXT
DRTAR U RET
چون مقدار RAM را یکراست در AR نمیتوان قرار داد پس ابتدا آن را به DR داده با دستور READ , سپس مقدار DR یعنی آدرس مستقیم شده را به ثبات آدرس یعنی AR می دهیم و چون کارمان تمام شده است حالا وقت آن است که برگردیم به جایی که INDRCT فراخوانی شده پس از RET استفاده شده.
حال برگردیم به تابع ADD .
تا ایینجا داشتیم :
NOP I CALL INDRCT
که اگر آدرسی که در AR قرار دارد غیر مستقیم باشد به این تابع می رویم و این آدرس را مستقیم می کنیم و سپس به خط دوم می رویم و اگر از اول مستقیم باشد ( یعنی شرط I برقرارنباشد ) به خط دوم می رویم پس در هر صورت وقتی به خط دوم می رسیم آدرس ما مستقیم است .
حال باید عمل ADD را انجام دهیم , ADD یعنی مقداری که در RAM است با مقداری که در AC است جمع شود و در AC قرار گیرد : AC <- M[AR] + AC
می دانیم برای جمع فقط AC و DR هستند که می توانند جمع شوند , AC که آماده است اما ما باید ابتدا مقدار RAM را در DR قرار دهیم و سپس جمع کنیم :
READ U JMP NEXT
ADD U JMP FETCH
که پرش به FETCH نیز بعد از کامل شدن اجرای هر تابع انجام می شود تا دستور بعدی گرفته شود و اجرا شود.
دستور BRANCH :
IF ( AC < 0 ) THEN PC <- AR
یعنی اگر AC منفی بود مقداری که در AR است را در PC قرار بده که این یعنی پرش در RAM یعنی ما میخواهیم دستور بعدی ای که اجرا می شود چیزی باشد که ما میخواهیم باید به PC مقدار دهیم.
اینجا چون تابع با شرط اجرا می شود ابتدا شرط را چک کنید سپس تابع را اجرا کنید.
به کد آن در شکل توجه کنید.
ابتدا چک کرده اگر AC منفی است ( S ) بپر به خط OVER وگرنه برو به خط بعد و تابع را تمام کن و به FETCH برگرد . حال اگر AC منفی باشد و به خط OVER برود تابع آغاز می شودکه ابتدا باید از مستقیم بودن آدرس مطمعن شویم سپس مقدار AR وارد PC می شود.
دستور STORE :
ما می خواهیم مقداری که در AC است وارد RAM شود اما این کار مستقیم امکان پذیر نمی باشد پس ابتدا آن را به DR داده و سپس WRITE ( M[AR] <- DR ) را انجام داده است.
دستور EXCHANGE :
می خواهیم مقداری که در RAM است با مقداری که در AC است جا به جا شود.
پس از اطمینان از مستقیم بودن آدرس , ابتدا مقدار RAM را در DR قرار داده , در کلاک بعدی همزمان جای AC و DR را عوض می کند ( در فصل ۵ در مورد همزمانی صحبت شد ) سپس مقدار DR را که مقدار قبلی AC را دارد در RAM می نویسد.
حال باید بدونیم که طبق شکل قبل و دو شکل قبل باید بدونید که ما از مخفف دستورات استفاده می کنیم در حالی که در اصل این دستورات اعدادی باینری هستند که کامپیوتر از طریق آن می تواند متوجه دستورات شود.
شکل بالا را در نظر بگیرید, حال به شکل زیر که باینری شده ی آن است توجه کنید :
که واضح است در هر خط به جای مخفف دستورات از باینری آن که در F1 , F2 , F3 , CD , BR , AD قرار میگیرد استفاده شده است.
لازم به ذکر است که برای پرش ( CAAL , JUMP ) به جای اسم خطی که می خواهیم به آن خط پرش کنیم شماره خط آن نوشته می شود برای مثال کد زیر را به باینری تبدیل می کنیم :
ADD U JMP FETCH
در اینجا از ADD استفاده شده که در F1 با کد ۰۰۱ وجود دارد , از F2 , F3 استفاده نشده که از NOP یعنی همون ۰۰۰ استفاده می کنیم , از CD : U استفاده شده که کد آن ۰۰ است , از BR : JMP استفاده شده که کد آن ۰۰ است و از AD از FETCH استفاده شده که آدرس آن همانطور که در شکل بالا می بینید برابر ۱۰۰۰۰۰۰ می باشد. پس داریم :
۰۰۱۰۰۰۰۰۰۰۰۰۰۱۰۰۰۰۰۰
به همین ترتیب برعکس هم می شود کد باینری را به کد مخفف شده تبدیل کرد به این صورت که از چپ به راست ۳ بیت برای F1 سپس ۳ بیت برای F2 , 3 بیت برای F3 , 2 بیت برای CD , ۲ بیت برای BR , 7 بیت برای AD در نظر بگیرید و طبق جدول آن را به کد تبدیل کنید.
حال چند مثال کد نویسی برای یادگیری بیشتر حل می کنیم , میخواهیم کد های زیر را به کد های قابل اجرا در کنترل ریز برنامه نویسی شده در آوریم :
M[AR] <- M[AR] + AC
پس از اطمینان از مستقیم بودن آدرس ابتدا M[AR] را در DR قرار داده سپس جمع می کنیم , چون حاصل در AC قرار می گیرد پس AC را به DR می دهیم و سپس در M[AR] می نویسیم:
NOP I CALL INDRCT
READ U JMP NEXT
ADD U JMP NEXT
ACTDR U JMP NEXT
WRITE U JMP FETCH
حال همین مثال را به گونه ای حل می کنیم که پس از اجرای کامل دستورات مقداری که از قبل در AC بوده تغییر نکند یعنی مقدار قبل از اجرای AC با مقدار بعد از اجرای AC برابر باشد :
باید در هنگام خراب شدن AC آن را به DR بدهیم و بعد پس بگیریم ( همزمانی در فصل ۵ صحبت شده )
NOP I CALL INDRCT
READ U JMP NEXT
ADD , ACTDR U JMP NEXT
ACTDR , DRTAC U JMP NEXT
WRITE U JMP FETCH
در خط سوم هنگام ADD کردن حاصل در AC قرار میگیرد و مقدار قبلی AC از بین می رود پس همزمان با محاسبه جمع , مقدار قبلی AC را به DR می دهیم تا خراب نشود و در خط بعد جایی که میخواهیم مقدار AC را در DR قرار دهیم برای WRITE کردن همزمان مقدار DR را در AC قرار می دهیم که مقدار قبلی خودش است.
مثال بعدی ( با فرض خراب نشدن مقدار AC ) :
IF ( AC = M[AR] ) THEN PC <- PC + 1
ما نمی توانیم دو مقدار را مقایسه کنیم برای مقایسه کردن باید منها کنیم سپس جواب را در AC قرار دهیم و بیینیم صفر شده یا نه ( با استفاده از Z ) و همچنین می شود فهمید منفی شده یا نه ( با استفاده از S ).
پس مقدار رم را با AC تفریق می کنیم سپس چک می کنیم ۰ شد یا نه سپس عملیات را انجام می دهیم :
NOP I CALL INDRCT
READ U JMP NEXT
SUB , ACTDR U JMP NEXT
NOP Z JMP OVER
DRTAC U JMP FETCH
OVER : INCPC , DRTAC U JMP FETCH
در خط سوم برای خراب نشدن AC آن را در DR قرار دادیم , خط ۴ چک شده که اگر AC یعنی حاصل تفریقی که اکنون در AC است اگر صفر شده برو به خط OVER در غیر این صورت برو به خط بعد.
در هر ۲ خط پایانی که یکی از آن ها با توجه به شرط اجرا خواهد شد مقدار قبلی AC که در DR قرار داده بودیم را به خودش برگرداندیم.
نکته : برای NOT کردن یک مقدار باید آن را به AC بدهید سپس با کمک دستور COM می توانید AC را NOT کنید.
نکته : برای اینکه چک کنید مقداری مثبت است ( X>0 ) باید آن را در AC قرار دهید و سپس یکبار چک کنید که منفی است یا نه ( S ) و یک بار چک کنید صفر است با نه (S) .مثال :
IF ( AC > 0 ) THEN PC <- AR
NOP S JMP FETCH
NOP Z JMP FETCH
NOP I CALL INDRCT
ARTPC U JMP FETCH
خط اول یعنی اگر AC منفی بود تمامش کن , خط دوم اگر AC صفر بود تمامش کن , به خط سوم که برسد یعنی AC مثبت بوده است پس دستور را اجرا می کنیم.
مثال : به کد زیر توجه کنید :
ADD : READ I CALL INDRCT2
ADD U JMP FETCH
سوال این است که ما باید تابع INDRCT2 را به گونه ای بنویسیم که این کد درست عمل کند.
می دانیم هنگام فراخوانی INDRCT ما از NOP استفاده می کردیم اما اینجا قبل از INDRCT از READ استفاده کرده یعنی مقداری که در RAM بوده را در DR قرار داده اما ما هنوز مطمعن نشده بودیم که آدرسی که داریم مستقیم است یا خیر یعنی ممکن است مقدار نا معتبری در DR قرار گرفته باشد و عملیات جمع اشتباه شود.
اول فرض کنید آدرس مستقیم است و اصلا تابع INDRCT2 فراخوانی نمی شود در این حالت کد درست عمل می کند چون در خط اول مقدار معتبر را به DR می دهد سپس جمع می کند.
حال فرض کنید آدرس غیر مستقیم باشد : پس از READ کردن ما وارد INDRCT2 میشویم و باید کاری کنیم که پس از بازگشت مقدار معتبر در DR باشد تا عملبات جمع انجام شود . خب حالا که قبل از تابع READ انجام شده چه مقداری در DR قرار گرفته؟
برای مستقیم کردن آدرس ما قبلا چکار میکردیم؟
برای مستقیم کردن ما READ میکردیم و سپس مقدار را به AR می دادیم.
حالا اینجا از قبل READ انجام شده یعنی الان آدرس معتبر در DR است تکرار می کنم الان در DR آدرس معتبر قرار دارد در حالی که ما اینجا باید پس از پایان تابع INDRCT2 باید مقدار معتبر را در DR قرار دهیم که این عمل را قبلا بعد از اجرای INDRCT در بدنه تابع اصلی انجام می شد.
خب پس متوجه شدیم باید در تابع INDRCT2 چکار کنیم : باید آدرس معتبر در DR را به مقدار معتبر تبدیل کنیم یعنی آدرس با به AR بدهیم و سپس مقدار آن آدرس را به DR بدهیم :
INDRCT2 : DRTAR U JMP NEXT
READ U RET
این هم از مبحث کد نویسی که به تمرین بیشتر شما نیز نیازمند است.
در انتها می خواهم به موارد سخت افزاری در مورد CAR بپردازم که این ثبات با چه چیز هایی در ارتباط است.
به شکل زیر توجه کنید :
همانطور که می بینید CAR از یک مالتی پلکسر یک مقدار دریافت می کند که این مقدار میتواند CAR +1 باشد ( افزایشگر به مقدار CAR یک عدد اضافه می کند ) , میتواند عدد حاصل شده از عملیات MAPPING باشد , می تواند AD باشد که در دستورات JUMP , CALL از آن برای پرش به دستور مورد نظر استفاده می شود , و می تواند مقدار SBR باشد یعنی مقداری که هنگام فراخوانی تابع در SBR ذخیره کیرده ایم و اکنون می خواهیم به آن آدرس برگردیم پس باید SBR را به CAR برسانیم.
حال به توضیح این می پردازم که چگونه انتخاب می شود که کدام مقدار وارد CAR شود.
به شکل زیر توجه کنید :
همین مقدار های CD , BR هستند که مشخص می کنند که در CAR چه مقداری قرار بگیرد به این صورت که CD در یک MUX تعیین میکند که شرط چیست و سپس باید چک کرد که شرط برقرار است یا نه که ما با برقرار بودن یا نبودنش کار داریم که در شکل بالا T این را تعیین می کند که آیا شرط CD برقرار است یا نه.
سپس بر مداری دیگر با توجه به برقرار بودن یا نبودن شرط در CD و با استفاده از دو بیت در BR تصمیم گیری می شود چه مقداری در CAR قرار گیرد.
به شکل زیر توجه کنید :
در این شکل T نشان دهنده برقرار بودن یا نبودن شرط و I0 , I1 همان BR می باشد , S0 , S1 نیز انتخابگر های مالتی پلکسر ورودی CAR است که باید تعیین کنیم چه موقع چه عددی باشد و البته تک بیت L که نشان می دهد SBR چه موقع باید مقدار دریافت کند.
در سطر اول گفته شده BR برابر ۰۰ است و T نیز ۰ است یعنی دستور JUMP است و شرط هم برقرار نیست پس ما باید CAR+1 را وارد CAR کنیم که برای اینکار باید ورودی اول MUX وارد CAR شود پس S0 , S1 باید ۰۰ باشند تا خروجی افزایشگر وارد CAR شود و واضح است که SBR هم نباید مقداری دریافت کند پس L برابر ۰ است.
سطر دوم : JUMP و شرط برقرار است پس AD باید در CAR قرار بگیره یعنی S0 , S1 برابر ۰۱ و SBR مقدار نمی گیرد.
سطر سوم : CALL و شرط برقرار نیست پس خروجی افزایشگر در CAR قرار میگیره یعنی S0 , S1 برابر ۰۰ و SBR نیز مقداری دریافت نمی کند.
سطر چهارم : CALL و شرط برقرار است پس AD در CAR قرار می گیرد یعنی S0 , S1 برابر ۰۱ و تنها در این شرایط SBR باید مقدار بگیرد پس L برابر ۱ می شود ( L همان LOAD می باشد برای SBR که در فصل ۵ در مورد این handle ها صحبت شد ) .
سطر پنجم : RET می باشد که بدون شرط اجرا می شود و باید مقداری که در SBR قرار دادیم را به CAR بدهیم که اینجا باید S0 , S1 برابر ۱۰ شوند و نیازی هم نیست SBR چیزی را ذخیره کند پس L برابر ۰ است.
سطر ششم : MAP که بدن شرط است و باید S0 , S1 برابر ۱۱ باشد تا عملیات MAPPING انجام شود و SBR هم نیاز نیست چیزی ذخیره کند پس L برابر ۰ است.
امیداورم از این فصل لذت برده باشید و به تسلط کافی دست پیدا کرده باشید.
در صورت مشکل یا سوال به بنده در سایت www.zerotohero.ir مراجعه فرمایید.
پایان فصل هفتم مانو
مطالب زیر را حتما مطالعه کنید
حسگرها و فناوریهای پوشیدنی و کاربردهای آنها در پزشکی
آشنایی با نمودار رابطهای (ER)
درخت دودویی
ساختمان داده درخت
مدار منطقی – گیت های منطقی
مدار منطقی-جبر بول
1 Comment
Join the discussion and tell us your opinion.
دیدگاهتان را بنویسید لغو پاسخ
برای نوشتن دیدگاه باید وارد بشوید.
عااالیه … خیلی ممنون از لطفتون