پروژه, توصیه شده, مقاله های سیسوگ

راه اندازی console و رجیستر W – بخش دوم CPU هشت بیتی

راه اندازی console و رجیستر W - بخش دوم CPU هشت بیتی

مقدمه

تا الان این CPU که در این پست نوشته ایم از کدهای دستوری BSF، BCF، GOTO و NOP پشتیبانی می کند، حالا زمان ایجاد رجیستر W و نوشتن کد های دستوری برای کنترل آن و راه اندازی console برای نمایش پیام های می باشد.

رجیستر W چیست

رجیستر W یک رجیستر عمومی است که می توان آن را با هر عددی مقدار دهی کرد، یا مقدار آن را به آدرس دیگر انتقال داد، و هربار مقدار جدیدی که به این رجیستر داده می شود جای مقدار قبلی را می گیرد.

اضافه کردن opcode های جدید به اسمبلر

حالا opcode های زیر را به Assembler اضافه می کنیم: که سه دستور اول مربوط به رجیستر W می باشند.

  • MOVLW
  • MOVWF
  • CLRW
  • CLRF
  • SLEEP

دستور MOVLW

این دستور مقدار عددی داده شده (از 0 تا 255) را در رجیستر W قرار می دهد:

دستور MOVLW

در MOVLW چهار بیت اول بیانگر opcode مربوط به دستور و هشت بیت بعدی برای مقدار دستور می باشند.

مثال: MOVLW 55 که مقدار 55 را در رجیستر W ذخیره می کند

دستور MOVWF

این دستور مقدار رجیستر W را در آدرس داده شده قرار می دهد (در این CPU ما 10 آدرس برای رجیستر و 16 آدرس برای RAM در دسترس داریم)

دستور MOVWF

در این کد 5 بیت از سمت راست بیانگر آدرس داده شده می باشد

مثال: MOVWF 06H که مقدار رجیستر W را در آدرس 06H به صورت هگز (برابر با 0x06) قرار می دهد، که رجیستر 6 مربوط به ورودی / خروجی ها می باشد.

دستور CLRW

این دستور برای پاک کردن (برابر با 0 قرار دادن) مقدار رجیستر W می باشد

دستور CLRW

این دستور همانند NOP می باشد و عملوندی ندارد و به صورت یکتا استفاده می شود و opcode آن همیشه ثابت است.

مثال: CLRW که مقدار رجیستر W را برابر با 0 قرار می دهد

دستور CLRF

این دستور مقدار آدرس داده شده را پاک می کند (برابر با 0 قرار می دهد).

دستور CLRF

در این دستور 5 بیت از سمت راست بیانگر آدرس داده شده می باشند و 7 بیت آخر برای opcode مربوط به دستور

مثال: CLRF 06H که مقدار آدرس 6 (پایه ورودی / خروجی CPU) را برابر با 0 قرار می دهد.

دستور SLEEP

این دستور CPU را به حالت خواب می برد و بعد از آن اتفاقی در CPU نمی افتد و PC یا شمارنده داخل CPU تغییری نمی کند و برای خروج از این حالت، نیاز هست که CPU را ریست (reset) کنیم.

دستور SLEEP

 

این دستور نیز مانند CLRW و NOP دارای کد دستوری 12 بیتی و همیشه ثابتی می باشد و عملوندی ندارد.

مثال: SLEEP که CPU را به حالت خواب می برد.

اضافه کردن دستور ها به CPU

بعد از مشخص شدن دستور ها برای assembler حالا زمان اضافه کردن آنها به CPU و تشخیص و اجرای آنها می باشد، قبلا بخش های مربوط به اضافه کردن دستورها را در پست که مربوط به CPU و پست مربوط به Wokwi گفته شده، حالا با تغییر و اضافه کردن کدهای آخرین پست، کدها را به CPU اضافه می کنیم.

اول از همه enum مربوط به opcode ها را آپدیت می کنیم و دستورات جدید را به آنها اضافه می کنیم:

اضافه کردن دستور ها به CPU

از خط های 6 تا 10 دستور های جدید می باشند

حالا تابع decode_inst را آپدیت میکنیم، که بخش تشخیص دستورا ها را دارد:

اضافه کردن دستور ها به CPU

کد بالا مربوط به بخش تشخیص opcode ها برای CPU می باشد که به تابع decode_inst اضافه شده است، و با توجه به هر opcode اطلاعات مربوط به صورت یک structure بازگردانده می شوند که برای بخش اجرا شدن مفید می باشند.

بعد از این کار زمان تغییر تابع soft_execute است، و دستور SLEEP را به آن اضافه می کنیم:

تابع soft_execute

کد مربوط به SLEEP از خط های 11 تا 13 می باشد.

کد زیر مربوط به حلقه اصلی CPU می باشد:

حلقه اصلی CPU

دستور SLEEP یکی دیگر از دستور هایی می باشد که تاثیری در حافظه نمی گذارد، حالا با تغییر حلقه اصلی بخش مربوط به اجرای دستور SLEEP را اضافه می کنیم:

دستور SLEEP

در کد بالا در صورتی که دستور SLEEP تشخیص داده شد و در نهایت در soft_execute مشخص شد دیگر شمارنده برنامه (PC) تغییری نمی کند و دستوری اجرا نمی شود (CPU به حالت “خواب” می رود)

بعد از اینکار زمان تغییر تابع execute می باشد اما اول نیاز است که توابع مربوط به رجیستر W را بنویسم:

تغییر تابع execute

در خط 1 متغیری برای رجیستر W مشخص شده و در خط های 4 و 9 دو تابع برای گرفتن مقدار رجیستر W و قراردادن مقداری برای آن وجود دارند (دلیل این که از این توابع برای این کار استفاده می کنیم این است که به خوانایی کد کمک می کند و می توان این متغیر ها را در فایلی دیگر قرار داد).

تغییرات تابع execute به صورت زیر می باشد:

تابع execute

با استفاده از کد بالا دستور های جدید با استفاده از آدرس و یا بیت های گرفته شده اجرا می شوند و memory مربوط به CPU آپدیت می شود

راه اندازی Console

قبل از راه اندازی console اول باید ببینیم که نحوه کار آن چگونه می باشد:

کنسول با استفاده از خروجی GPIO یا رجیستر 6 کار می کند، هنگامی که بیت 8 ام (شروع از 1) پایه برابر با 1 می شود، وظیفه emulator می باشد که 7 بیت قبلی را تبدیل به کاراکتر کند (مقدار عددی کاراکتر) و پس از آن می توان آن کاراکتر را به printf و “c%” در خروجی چاپ کرد:

راه اندازی Console

چاپ کردن Hello World با استفاده از Console

تا الان با نحوه کارکرد کنسول آشنا شده ایم، حالا برنامه ای می نویسیم که با استفاده از آن پیام “Hello, World” را در console چاپ کنیم.

برای این کار از opcode های جدیدی که مشخص کرده ایم استفاده می کنیم، هر حرف به صورت زیر نوشته می شود:

چاپ کردن Hello World با استفاده از Console

  • در خط 1 مقدار عددی حرف H را به رجیستر W می دهیم
  • در خط 2 مقدار رجیستر W را به پایه 6 (GPIO) که برای ورودی خروجی می باشد، می دهیم و console نیز از این پایه استفاده می کند
  • در خط 3 با استفاده از دستور BSF بیت 8 ام (شروع از 0) را برابر با 1 قرار می دهیم، به صورت کلی قرار گرفتن این بیت به console می گوید که کاراکتر را چاپ کن

حالا این کار را برای تمام حروف ها انجام می دهیم و نتیجه به صورت زیر می شود:

نتیجه کنسول نهایی

برای دریافت برنامه assembly از این لینک استفاده کنید:

https://github.com/Empitrix/assembler/blob/master/examples/hello.asm

برای دیدن دستور های مربوط به assembler:

https://github.com/Empitrix/assembler

برای دیدن دستور های مربوط به CPU (میکروکنترلر):

https://github.com/Empitrix/8bitcpu

انتشار مطالب با ذکر نام و آدرس وب سایت سیسوگ، بلامانع است.

شما نیز میتوانید یکی از نویسندگان سیسوگ باشید.   همکاری با سیسوگ

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *