بررسی معماری MIPS

خب، همونطور که داریم سلسله آموزش های ساخت کامپیوتر ساده در Logisim رو دنبال میکنیم، گفتم این وسط یه توضیحی هم در مورد معماری MIPS داشته باشیم. در واقع MIPS یکی از ساده ترین و کم دستور ترین معماری های ممکنه، و البته پیاده سازی دوبارش در نرم افزارهایی مثل Logisim بسیار ساده. میشه.

این یک ALU بسیار ساده بر اساس میپس هست (که البته یک بیتی پیاده شده) :

MIPS

در اینجا، برای تفریق مدار جداگانه ای در نظر نگرفته، بلکه مقدار B رو با یک، XOR کرده (هوشمندانه به نظر میرسه، نه؟) و از less هم برای مقایسه، از یک مالتی پلکسر ۸ به ۱ هم برای انتخاب عملیات استفاده شده (به جای استفاده از دیکدر و گیت های AND )، در کل میشه یک ساختار خیلی قشنگ براش قائل شد، البته بهتر از این هم میشد الگوریتم هایی مثل تفریق رو هم پیاده کرد (مثلا با استفاده از یه mux میشد انتخاب کرد که خود B نیازه یا نقیضش؟ و البته نیاز بود که cin هم حتما روشن شه که مکمل ۲ گرفته شه).

زبان ماشین این ALU هم خیلی سادس، به ازای مقدار ۰ ، عملیات AND ، به ازای ۱ عملیات OR ، به ازای ۲ عملیات XOR ، به ازای ۳ عملیات NOR ، به ازای ۴ عملیات ADD و به ازای ۵ عملیات مقایسه رو انجام میده (البته برای مقایسه هم میشه از XNOR استفاده کرد و تساوی رو سنجید).

امیدوارم که این مطلب به دردتون خورده باشه، همچنین میتونید این معماری رو پیاده کنید و نتیجش رو حتی روی برد بُرد بیارید 🙂 .

موفق باشید.

Share

ساخت یک کامپیوتر ساده در Logisim – قسمت دوم (مجموعه دستور العمل ها)

در قسمت قبلی، چالش رو مطرح کردیم که کامپیوتر هشت بیتی خودمون رو بسازیم. ببینیم چه مداراتی نیاز داریم؟!

خب ما دو ورودی هشت بیتی A و B رو خواهیم داشت، پس به این موارد نیاز داریم :

  1. مداری برای NOT کردن ورودی A
  2. مداری برای NOT کردن ورودی B
  3. مداری برای AND کردن هر دو ورودی
  4. مداری برای OR کردن هر دو ورودی
  5. مداری برای جمع کردن دو ورودی
  6. مداری برای تفریق دو ورودی

خب، چون ما از یک قطعه به اسم «دیکدر» برای انتخاب دستورات استفاده میکنیم، و دیکدرها هم یک ورودی با سایز n میگیرن، و خروجی اونها «دو به توان n» هست، و ما اینجا «مجموعه دستور العمل» یا Instruction Set مون دارای ۶ دستور هست، بهینه ترین حالت استفاده از یک دیکدر ۳ به ۸ هست. خب، با این حساب، باید کد عملیات ها یا Operation Code ها رو به این شکل تعریف کنیم :

Operation Code
NOT A 000
NOT B 001
AND A, B 010
OR A, B 011
ADD A , B 100
SUB A, B 101

خب الان ما میدونیم که کامپیوتر محترم باید چه دستوراتی رو اچرا کنه. در واقع، وقتی میگیم ۰ ، کامپیوتر اون رو به دیکدر میده و میفهمه که باید نقیض A رو بهمون بده. وقتی ۱ رو فراخوانی میکنیم، باید نقیض B بهمون داده شه، وقتی میگیم ۵ در واقع مقدار B رو از A کم میکنیم و … . با توجه به این که الان، ما یک دیکدر ۳ به ۸ در مدار «واحد محاسبه و منطق» داریم، میتونیم ۴ دستور العمل دیگه هم بهش اضافه کنیم (با شما 🙂 ). در قسمت بعدی این آموزش، میرسیم به این که ورودی ها و خروجی ها رو چطوری مدیریت کنیم. بعدش هم در مورد ساختار کلی ALU صحبت میشه و بعد از چند پست دیگه، یک ALU کامل با هم خواهیم داشت. پس فعلا در مورد بلاهایی که سر ۸ بیت ورودی میشه آورد فکر کنید و شاد باشید 🙂

Share

ساخت یک کامپیوتر ساده در Logisim – قسمت اول

بالاخره یه سری پست جدید تصمیم گرفتم بنویسم، و خب این سری قراره که مرحله به مرحله پیش بریم تا یک کامپیوتر ساده بسازیم. تنها دانشی که شما برای این سری از پست ها نیاز دارید :

۱. دونستن کمی مدار منطقی (که قبلا در وبلاگ راجع بهش حسابی صحبت کردم)

۲. بلد بودن کار با Logisim (که میشه گفت مثل نقاشی کشیدن میمونه و همین پست ها رو دنبال کنید یاد میگیرید.).

راه اندازی محیط کار

برای این که بتونیم مداراتمون رو طراحی و آزمایش کنیم، نیاز داریم که نرم افزار Logisim رو داشته باشیم. یه نسخه خوب از این نرم افزار به اسم Logisim Evolution طراحی شده که کار ما رو به شدت ساده تر کرده، خروجی گرفتن ازش بی دردسر تره، و همچنین مدارات و ویژگی هاشون دقیق تر طراحی شده. برای دانلود و نصب و روش راه اندازیش میتونید به اینجا برید. فقط هم نیازه که جاوا روی سیستمتون نصب باشه.

چالش های پیش رو

خب، برای این که بیایم یک کامپیوتر بسیار ساده طراحی کنیم نیاز داریم که یک سری سوالات از خودمون بپرسیم و جواب بدیمشون، اینطوری راحت تر میتونیم مدارات مورد نیاز رو طراحی کنیم و از پیچیدگی محصول نهایی جلوگیری کنیم.

کامپیوتر ما باید چه عملیاتی انجام بده؟

یک کامپیوتر ساده که بتونه به راحتی قابل درک هم باشه، هم باید Word Size کوچیکی داشته باشه (توی آموزش ها با ۸ بیت میریم جلو) و هم Instruction Setش باید کوچیک باشه. یک سری دستور پایه هست که هر کامپیوتری میتونه انجامش بده، ما کامپیوترمون رو اینطور طراحی مکنیم که AND, OR, NOT رو بتونه انجام بده، علاوه بر اون بتونه جمع و تفریق هم بکنه. پس باید :

  1. مداری طراحی کنیم که بتونه ۸ بیت رو NOT کنه
  2. مداری طراحی کنیم که بتونه ۸ بیت رو OR کنه
  3. مداری طراحی کنیم که بتونه ۸ بیت رو AND کنه
  4. و مدار(ها)ی طراحی کنیم که بتونن ۸ بیت رو جمع و تفریق کنن.

حالا به سادگی میتونیم بفهمیم که چی میخوایم. البته این صرفا واحد محاسبه و منطق هست، ما باید یک واحد حافظه، یک واحد کنترل و چند واحد حافظه موقتی و کوچک هم طراحی کنیم که با چسبوندنشون به هم، بتونیم به کامپیوتر کامل برسیم.

در پست های بعدی، زیرمدارهای کامپیوتر خودمون رو میسازیم. در این پست صرفا با کامپیوتر ساده و کوچیکمون آشنا شدیم 🙂

Share

نوشتن اسمبلی ۳۲ بیت

در گذشته، پست هایی که در مورد اسمبلی قرار دادم، همه در مورد اسمبلی ۱۶ بیت بودن اما حالا میخوایم بریم سراغ اسمبلی ۳۲ بیت. خب فرق ۱۶ با ۳۲ بیت در چیه؟!

اولین نکته، سایز ثبات هاست! در ۱۶ بیت در هر ثبات میتونستیم حداکثر یک مقدار ۴ رقمی هگزادسیمال ذخیره کنیم ولی در ۳۲ بیت این مقدار به ۸ رقم میرسه! حالا خیلی مسائل دیگه مثل دیتاباس و کنترل باس و … که بماند (چون اینجا داریم برنامه نویسی میکنیم و بیشتر با ثبات ها کار داریم).

اینجا، قضیه یه فرقای کوچولویی داره، مثلا اسمبلر nasm قراره استفاده بشه (گرچه قبلا در ساخت اون سیستم عامل کوچک ازش استفاده کردیم) و همچنین وقفه ها و system call هایی که استفاده میکنیم شماره و مقدارشون و مکانشون متفاوته.

بیاید این برنامه رو در نظر بگیریم :

کد   
section .text
	global_start
 
_start:
	mov edx, len
	mov ecx, msg
	mov eax, 0x04
	int 0x80
 
	mov eax, 0x01
	int 0x80
 
section .data
	msg db 'Hello, World!', 0xa
	len equ $ - msg

 

خب در بخش اول، تابعی که نیاز داریم فراخوانی کنیم رو تعریف کردیم. بعدش اومدیم start رو نوشتیم. حالا بیاید این بخش رو بررسی کنیم :

کد   
mov edx, len
mov ecx, msg
mov eax, 0x04
int 0x80

اینجا، مقدار طول رشته ای که خواستیم چاپ کنیم رو توی EDX یا رجیستر داده قرار دادیم. بعدش اومدیم پیامی که میخوایم چاپ بشه رو قرار دادیم درو نECX .

بعدش سیستم کال ۴ یا sys_write رو توی eax قرار دادیم و وقفه ۸۰ رو صدا زدیم. حالا وقفه ۸۰ با مقدار ۴ که توی eax ذخیره شده، میگرده دنبال رشته ای که توی ecx هست و بعدش چاپش میکنه.

حالا بخش دوم کد سگمنت رو بررسی میکنیم :

کد   
mov eax, 0x01
int 0x80

اینجا هم مقدار ۰۱ یا sys_exit رو وارد eax کردیم، تا برنامه پس از اجرا، خارج شه. بعد از این هم باز وقفه ۸۰ رو صدا زدیم.

بخش دیتا هم، مثل همه برنامه های قبلی، تمام داده های مورد نیاز رو با Directive ها تعریف کردیم که بتونیم به راحتی توی کد سگمنت ازشون استفاده کنیم و چون قبلا توضیح داده شده، دیگه دوباره کاری نمی کنم. فقط این پست رو نوشتم تا فرقهای اسمبلی ۳۲ و ۱۶ بیت رو ببینیم. که درآینده بسطش خواهم داد به ۶۴ بیت.

امیدوارم که این پست، بدردتون خورده باشه.

موفق و موید باشید!

Share

درآمدی بر پردازنده ها

ALUwithRegister

پس از مدتها تحقیق و بررسی در مورد پردازنده های مرسوم، و همچنین خوندن داکیومنت های مربوط به ساخت و پیاده سازی پردازنده ها، تصمیم گرفتم یک داکیومنت ساده دست و پا کنم، که توی اون از ساده ترین قطعات و بخش های کامپیوتر، به یک پردازنده ساده برسیم که بتونه چند عملیات انجام بده و نتیجه رو ذخیره کنه.

داکیومنت از اینجا قابل دریافت هست.

با تشکر.

Share

زبان ماشین، رمزگشای دستور العمل

در پست های گذشته بسیار بسیار در مورد زبان ماشین و اسمبلی بحث کردیم، اما این بار میخوایم بررسی کنیم که یک دستور، چطور کار میکنه. برای این کار، ما از ساده ترین دستورات استفاده میکنیم. قبل از اون، باید ببینیم که چه اتفاقی میفته که دستورات ما، شناسایی میشن! پس میایم و دستوراتمون رو بررسی میکنیم.

یک دستور در ماشین چطور خونده میشه؟

این خیلی مهمه که بدونیم یک دستور به چه شکلی خونده میشه. بسیار خوب، دستور زیر رو در نظر بگیرید :

کد   
MOV AX, 0

 

این دستور ماشین کد به این شکل داره :

کد   
B8 0000

 

که البته این ماشین کد، یک ماشین کد هگزادسیمال هست. اون چهار صفری که داریم که مقداری هست که خواستیم توی AX قرار بدیم و باهاش کاری نداریم، ولی B8 ما ، همون دستوریه که لازمه رمزگشایی شه و به صورت دو دویی به این شکل در میاد :

کد   
1011 1000

 

خب ما یک «دیکدر» (که یک مدار متشکل از n ورودی و دو به توان n خروجی هست) داریم، که این اعداد رو به ترتیب روشن و خاموش میکنه، و به این شکله که ما به  دستور میرسیم. در واقع مدارات مربوط به دستور رو خواهیم داشت.

بسیار خوب، حالا که میدونیم چه چیزی باعث میشه که ما بتونیم زبان ماشین رو درک کنیم، بیایم بررسی کنیم که :

زبان ماشین از چند بخش تشکیل شده؟

زبان ماشین، اول به صورت اسمبلی نوشته میشه که به زبون انسان خیلی خیلی نزدیکه. یعنی هرکس کمی انگلیسی بدونه میدونه که کلمه ای مثل ADD یعنی جمع کردن. اما، حالا مشکلی که هست اینه که وقتی «اسمبلی» به «آبجکت کد» یا همون کد هگزادسیمال تبدیل میشه رو هرکسی نمیتونه بخونه. پس راه حل چیه؟

اول باید ببینیم که یک خط آبجکت کد از چیا تشکیل میشه! بیاید این مثال رو در نظر بگیریم باز :

کد   
MOV AX, 0 ;B8 0000

 

خب اینجا من آبجکت کد رو به صورت کامنت در آوردم. دو بخش داریم، یکیش چهارتا صفر، که بهش عملوند یا Operand میگیم و دیگری «کد عملیات» یا Operation Code هست. مثلا برای انتقال به AX همیشه از B8 استفاده میشه. چرا؟ چون اینتل اینطور خواسته 😀 . بعد از این، این کد هگزادسیمال به یک کد باینری تبدیل میشه که CPU میتونه اون رو برای ما اجرا کنه.

از کجا آبجکت کد رو بخونیم؟

همه اسمبلر های موجود میتونن فایلی تولید کنن که آبجکت کد، سمبلهای به کار رفته و … رو شامل شه، و در اسمبلر MASM این فایل با پسوند LST ساخته میشه. شما میتونید با باز کردن این فایل با یک ویرایشگر متنی و خوندنش، ببینید که هر دستوری چه کدی رو داره.

یک برنامه نمونه

خب، من یک برنامه اسمبلی خیلی ساده نوشتم که اجرا کردنش هیچ خروجی ای نداره (:D ) ولی خب آبجکت کد ها تولید شده و اسمبل بدون مشکل صورت گرفته. این برنامه با آبجکت کدهاش به صورت کامنت به این شکله (بررسی دستور MOV در ۱۲ حالت مختلف) :

کد   
.MODEL SMALL
.8086
.STACK 
.DATA
.CODE
MOV AX, 0 ;B8 0000
MOV BX, 0 ;BB 0000
MOV CX, 0 ;B9 0000
MOV DX, 0 ;BA 0000
MOV AH, 0 ;B4 00
MOV BH, 0 ;B7 00
MOV CH, 0 ;B5 00
MOV DH, 0 ;B6 00
MOV AL, 0 ;B0 00
MOV BL, 0 ;B3 00
MOV CL, 0 ;B1 00
MOV DL, 0 ;B2 00
END

برای جلوگیری از ابهام هم مقداری که توی رجیسترها ریخته شده صفر هست، به این شکل کد ماشین بسیار ساده تر شده.

تا پست های بعدی، و اسمبلی بیشتر، موفق و موید و آزاد و شاد باشید! 🙂

Share

روز آفتابی و لامپ روشن

سلام. در این مطلب، قصد داریم در مورد ساختار کامپیوتر بحث کنیم. البته بیشترین چیزی که توی این مطلب بهش پرداخته میشه، دروازه های منطقی هستند و این که چطور میتونیم اون ها رو بسازیم.

بسیار خوب، عنوان مطلب به قدر کافی گویا هست که قراره چی رو به چی ربط بدیم، ولی بیاید این مثال رو در نظر بگیریم :

یک اتاق داریم که پنجره های زیادی داره و موقعیتش طوریه که در طول روز، بسیار نورگیره. واردش میشیم و می بینیم که یه لامپ روشنه. بعد دنبال کلید میگردیم. می بینیم که دو تا کلید کنار در هست، که هردو در وضعیت خاموش قرار داره. اولین احتمالی که پیش خودمون در نظر میگیریم، اینه که برقکار محترم کلید رو برعکس بسته. خب میگیم ایرادی نداره. یکی رو میزنیم، چراغ خاموش نمیشه. برش میگردونیم به حالت اول و اون یکی رو میزنیم. بازم چراغ خاموش نمیشه. یهو کنجکاو میشیم که هر دو کلید رو با هم در حالت روشن قرار بدیم، اون موقعه که می بینیم چی شد؟ چراغ خاموش شد!

حالا چه چیزی باعث شد که چراغ ما خاموش بشه؟ اینجاست که به جادوی ترانزیستورها باید ایمان بیاریم. در واقع دو کلید ما به یک مدار به این شکل وصل هستند :

0 -NAND Gate using transistors

 

این مدار، یک مدار یا بهتر بگم دروازه منطقیه که بهش NAND میگن. این مدار رو ما توی اون کلید قرار دادیم، و جدول درستیش به این شکله که هر وقت هر دو ورودی صحیح باشن، خروجی غلط میشه. حالا برای نمایش دادن بهتر این گیت، از این نماد استفاده میشه :

1- NAND gate

خب، سایر گیت ها (که با نماد های دیگه ای نشون داده میشن) رو میتونیم از این گیت بسازیم. اما چیزی که هست اینه که این گیت، چیزیه که کامپیوتر رو میسازه. در واقع در عمده IC هایی که خریداری میکنیم تعداد زیادی گیت NAND قرار داره که با وصل کردنش به هم، میتونیم گیت های دیگه ای رو هم بسازیم.

2-NAND Logic

خب، حالا فرض کنیم که به جای دو تا ورودی، یه ورودی دادیم به گیت NAND . یعنی از یک کلید، دو سیم به هر دو ورودی گیت وصل کردیم، به این شکل :

3-NOT Logic using NAND

حالا، اگر این کلید رو بزنیم، خروجی غلط و اگر خاموشش کنیم خروجی درست میشه. این ترکیب رو «نقض کننده» یا NOT هم بهش میگیم. در واقع گیت NOT که یک گیت با یک ورودی هست رو میتونیم به این شکل بسازیم.

الان میدونیم که یک NOT یا نقیض وجود داره. حالا میتونیم به جای اون ورودی، یک NAND با دو ورودی قرار بدیم که به این شکل در بیاد :

4-AND Logic using NAND

خب این مدار، یکم پیچیده شد. ولی دقت کنید که داره نقیض نتیجه NAND رو به ما میده. یعنی چی؟ یعنی در صورتی خروجی درست میشه که هر دو ورودی درست باشن. این منطق و این مدار هم که AND هست، و اگر جبر بول رو کمی بدونید میدونید که از بیسیک ترین دستورات جبر بول هست.

حالا، یه مدل دیگه این گیت ها رو پیش هم میچینیم. چطوری؟ این بار به جای نقض کردن نتیجه، نقیض ورودی ها رو به عنوان ورودی میدیم به یک گیت NAND . در واقع به این شکل :

5-OR Logic using NAND

حالا نتیجه به این شکل هست که «درصورتی که حداقل یکی از ورودی ها درست باشه، نتیجه درست میشه». و این منطق، منطق OR هست. در واقع گیت OR رو هم با NAND پیاده سازی کردیم.

یک مدار دیگه هم میمونه که نوع خیلی خاصی از OR هست. در واقع به این شکله :

6-XOR Logic using NAND

توی این گیت جدید، ما در واقع وقتی به نتیجه درست میرسیم، که تعداد «فرد» از ورودی ها (در اینجا یک، چون دو تا ورودی بیشتر نداریم) درست باشن. این منطق و این گیت رو «یای انحصاری» یا XOR میگن. اگر یک IC داشته باشیم که ۵ تا گیت NAND داخلش باشه، میتونیم ازش یک XOR بسازیم.

همه ما میدونیم که این گیت ها خودشون نماد انحصاری دارن و وقتی قراره چیزی با استفاده ازشون طراحی کنیم، بهتره (و باید!) از نمادهای خودشون استفاده کنیم، ولی یکی از دلایلی که این مطلب رو نوشتم این بود که میخواستم شما رو با ساختار درونی گیت ها آشنا کنم، همچنین میخواستم بررسی کنم که با استفاده از IC هایی که گیت NAND داخلشون هست، چطور میشه به سایر گیت ها رسید.

سال نو مبارک، موفق باشید 🙂

Share

دیدار با 8086 + کد روشن و خاموش کردن LED

نرم افزارهای زیادی برای کار با مدارات، تراشه ها و سایر دیوایس های الکترونیکی ساخته شده، ولی دو روزی هست که با Proteus دارم کار میکنم و میتونم بگم در این زمینه، از بهترین هاست. یکی از خوبی هاش داشتن تراشه های متعدد، با قابلیت اجرای برنامست. یکی از معروف ترین ریزپردازنده هایی که در این نرم افزار به کار رفته، پردازنده 8086 از اینتل هست. من این رو با این پردازنده ساختم (البته اصلا و ابدا مطمئن نیستم که مدارم درست باشه! ولی خود برنامه ایرادی ازش نگرفت) :

8086led

 

خب این مدار قراره چه کنه؟! قراره به کمک 8086 و یک مدار مجتمع 8255 ، چند تا LED رو به ترتیب خاموش و روشن کنه. یکی از ویژگی های پرتئوس اینه که تراشه هایی که داخلش هستند، همه برنامه پذیرند. البته شما باید برنامه هاتون رو بنویسید بعد اسمبل (یا کامپایل، بسته به نوع برنامه) کنید و بعد فایل اجراییتون رو به خورد تراشه بدید. بسیار خوب، برنامه ای که برای روشن و خاموش کردن LED نوشتم اینه :

کد   
.MODEL SMALL
.8086
.STACK
.CODE
MOV AL, 80
MOV DX, 0FF36h
OUT DX, AL
BEGIN: MOV AL,00
MOV DX, 0FF30h
OUT DX, AL 
CALL DELAY
MOV AL, 0FFh
OUT DX, AL 
CALL DELAY 
JMP BEGIN 
DELAY: MOV CX, 0FFFFh
P0 : DEC CX 
JNE P0 
RET
.DATA
END

خب، این برنامه رو باید با masm32 اسمبل کنید، که مراحلش به این شکله (مراحل اسمبل و لینک کردن در سیستم عامل ویندوز اینطوره، برای لینوکس هم سعی میکنم راه حلش رو پیدا کنم) :

کد   
ml /c /Zi /Zd LED.asm
link16 /CODEVIEW LED.obj,LED.exe,,, nul.def

دقت کنید که کد ها باید پشت سر هم وارد شن، همچنین ، بعد از این عملیات، چنانچه OpCode ها رو بخواید بخونید، میتونید از فایل LST تولید شده توسط اسمبلرتون استفاده کنید، که من اینجا OpCode رو میذارم (حواستون باشه این فقط برای کد سگمنت هست) :

OpCode

این هم از آپکد های این برنامه.

حواستون باشه مداری که کشیده شده ممکنه درست نباشه، در صورتی که برنامه درست اجرا میشه (برنامه تست شده و از این بابت مطمئنم).

امیدوارم شما هم با 8086 لحظات شادی رو تجربه کنید، درسته که یه پردازشگر قدیمیه، ولی کار باهاش شدیدا فانه!

موفق باشید 🙂

Share

ساخت یک کامپیوتر ۴ بیتی ساده با استفاده از مدارات منطقی

یک زمانی، حتی فکر کردن به این که بتونیم با چندتا مدار ساده یک کامپیوتر (حتی ۴ بیتی) هم داشته باشیم، احمقانه و ناممکن به نظر میرسید. چرا که هزینه شبیه سازی خیلی از مدارها و تستشون بسیار بالا بود. اما توی این دوره، شما با خوندن چند تا داکیومنت و نصب چند نرم افزار ساده، میتونید کامپیوتر خودتون رو بسازید. بسیار خوب، منبع این پست ، این مقالست که یک ویدئوی خوب هم داره. توی این مقاله به جای استفاده مستقیم از مدارات منطقی، اومدن و از ترانزیستور استفاده کردن، اما باز هم استفاده از ترانزیستور منطقی به نظر نمیرسه، چرا که مدارهای منطقی کوچک ترن و فهمشون هم راحت تره.

مدارهای منطقی چی هستن؟

به صورت خیلی ساده بخوام این رو توضیح بدم، میگم مجموعه ای از ترانزیستور ها که عملیات منطقی (با جبر بول) مثل «و» و «یا» و «نفی» رو انجام میدن. و از ترکیبشون هم میشه مدارهای پیچیده تر یا مدارهای منطقی دیگه رو ساخت. برای فهم بهتر این قضیه، مقاله ویکیپدیا در این باره رو بخونید. توی این پست فرض بر اینه که شما، مدارهای منطقی رو بلدید و میدونید که چی هستن و چی کار میکنن.

برای پردازنده کوچکمون چی نیازه؟

اول از همه، نیاز داریم که یک مدار Adder بسازیم. مدارهای Adder معمولا از چند تا Full Adder یک بیتی تشکیل میشن، و هر فول ادر یک بیتی هم از دو تا Half-adder .

برای ساخت Half-adder کافیه که یک بار ورودی A رو NOT کنیم و با B اون رو AND کنیم، سپس B رو NOT کنیم و با A اون رو AND کنیم. آخر هم نتیجه دو تا AND رو با هم OR کنیم. برای بدست آوردن رقم نقلی هم کافیه که A و B رو مستقیما با هم AND کنیم.half-adder2

مدار Half Adder نهاییمون به این شکل میشه. اما استفاده مدوام از NOT و AND و OR باعث سخت شدن توسعه ماشین میشه، پس از مجموعه ای که برای ساخت Half Adder استفاده کردیم میتونیم صرف نظر کنیم و از مدار XOR استفاده کنیم. البته همچنان برای رقم نقلیمون به AND نیاز خواهیم داشت.

بسیار خوب، برای Full Adder نیاز داریم که از پیش تعیین کنیم رقم نقلی ای وجود داره؟ یا نه! و برای این کار غیر از A و B یک ورودی به اسم Carry In یا «رقم نقلی ورودی» خواهیم داشت. و سپس، رقم نقلی ورودی رو باید به عنوان ورودی به یک Half-Adder دیگه بدیم. سپس، نتیجه AND شدن A و B رو با نتیجه AND شدن اولین Half-Adder و Carry In رو با هم OR کنیم تا رقم نقلی کلی بدست بیاد. پس مدار ما به این شکل خواهد شد :

full adderخب، این دو مدار رو الان ساختیم. قدم بعدی، ساختن کامپیوترمونه!

برای ساختن یک Adder چهار بیتی، باید به این شکل فول ادر ها رو کنار هم بچینیم :

Slide11همونطور که دیدید، این روش چیدن Adder ها پشت هم، مدل Ripple Carry نامیده میشه. خب، این کامپیوتر کوچک، میتونه اعداد ۰ تا ۱۶ (در دنیای بدون علامت و با در نظر گرفتن رقم نقلی) و -۱۶ تا ۱۵ (در دنیای علامت دار و بدون در نظر گرفتن رقم نقلی) رو به ما نمایش بده. با خاموش و روشن کردن به موقع مدارها عملیات جمع و تفریق رو میتونید انجام بدید.

من خودم با ترکیب این مدارها، این رو ساختم، و بیت ها  رو با لامپ نشون دادم :

4-bit computer simulation

برای شبیه سازی چه نرم افزاری نیازه؟

من برای کشیدن نقشه Half Adder و Full Adder از تخته وایت برد اتاقم (بله! تخته وایت برد توی اتاقا الزامیه!) و نرم افزار Logisim (موجود در مخازن اوبونتو) استفاده کردم. برای شبیه سازی کلی ماشین هم از Logic.ly که آزمایشگاه آنلاین داره استفاده کردم. البته هر نرم افزار دیگه ای میتونه بهتون در شبیه سازی کمک کنه. حتی میتونید با VHDL هم بنویسیدش و تستش کنید!

امیدوارم که این پست هم براتون مفید واقع شده باشه!

موفق باشید.

Share

توسعه سیستم عامل – طراحی IDT, IRQ و ISR

اگر یادتون باشه، مدتهای پیش، یک سری مقاله نوشتم، که آخرین مقاله این بود. توی حدود چهار تا مقاله، بررسی کردیم چطور میتونیم یه سیستم عامل ساده و ۱۶ بیتی بنویسیم. اونقدری نگذشت که تصمیم گرفتم برنامه نویسی رو به C تعمیم بدم و سپس NanOS رو بعنوان نسخه اولیه نوشتم، تجربه جالبی بود چون یه درایور ساده کارت گرافیک و کیبرد داشت و چند تا پیام میتونست نشون کاربر بده. اونقدری نگذشت که یه تجمعی به اسم «بنیاد نانو» درست کردیم که NanOS رو توضیح بدیم. NanOS الان سه تا چیزی رو داره که خیلی جالبن : IDT, IRQ  و ISR .

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

کد   
int 21h

خب همونطور که توی مقالات قبلی هم گفتم، int اینجا به معنای «عدد صحیح» نیست، بلکه به معنای «وقفه» است. وقفه های سخت افزاری و نرم افزاری که تا الان استفاده کردیم چه کار میکردن؟ عملکرد پردازنده رو متوقف میکنن و میگن که یه کار جدید انجام بده (به ساده ترین زبان ممکن!). خیلی راحت بگم فرض کنید توی یک کلاس دارید درس میدید (عمل جاری) ، یک نفر در میزنه و شما کار درس دادن رو متوقف میکنید و اینجاست که وقفه اجرا میشه (عمل جدید). خب IDT چیه؟ IDT مخفف Interrupt Descriptor Table ــه که به معنای «جدول توضیح وقفه ها» ست. این جدول، یک ساختمان داده‌ست که توش توضیح میدیم پردازنده چه جوابی باید به وقفه هایی که بهش وارد میشه بده. در این بین یه IRQ یا Interrupt Request داریم که درخواست دهنده وقفه هاست. درخواست دهنده وقفه، توی خود پردازنده وجود داره، و ما برای استفاده ازش باید براش کد بزنیم. کار IRQ چیه؟ این که نسبت به وقفه ها واکنش نشون بده و سیگنال های مربوطه رو بفرسته. سپس، با استفاده از هندل کننده وقفه ها جواب وقفه ها رو بسنجه، یا برنامه ای رو متوقف کنه و به برنامه جدید اجازه اجرا بده.

خب، در نهایت باید Interrupt Service Routine یا ISR داشته باشیم. ISR کارش کلا اینه که بیاد و چک کنه که وقفه درست انجام شده یا نه، بعدش، بیاد و یک مقدار منطقی به ما بده، که بفهمیم وقفه درست انجام شده یا نه.

بعنوان یک جمع بندی نهایی، میشه گفت که ما اول باید بگیم چه وقفه هایی داریم و هرکدوم چه میکنه (IDT) ، بعد همه اینا رو با یک قطعه خاص تست کنیم (IRQ) و نهایتا با یک نرم افزار از درست کار کردن وقفه هامون مطمئن شیم (ISR). کاربرد این قضیه چیه؟ فرض کنیم سیستم عامل تا حدی پیشرفت کرد و تونست برنامه اجرا کنه، با استفاده از جدول و هندل کننده های وقفه ها، میتونیم برای سیستم عامل خودمون یه اسمبلر طراحی کنیم، کامپایلر ها رو روش بیاریم و برنامه هایی که دسترسی سطح پایین میخواند رو اجرا کنیم.

موفق باشید 🙂

Share