پاسخ : برسی یک سیستم 386
1. مقدمه ای در مورد وقفه ها
2. نوشتن یک بوت لودر ساده با اسمبلی
3. اسمبل کردن بوت لودر با NASM
وقفه ها : از اونجایی که داشتن اطلاعات کاملی از وقفه ها برای نوشتن یک سیستم عامل ضروری و اجباریه. و من نمی تونم یه آموزش کامل از این موضوع رو اینجا بزارم، توصیه می کنم اگه اطلاعاتتون تو این زمینه کم هستش مطالعاتتون رو تو این زمینه بیشتر کنید. ولی یه توضیح مختصر درباره وقفه ها برای کسایی که هیچ اطلاعی ندارند میتونه مفید باشه.
وقفه ها در واقع یه سری از توابع نوشته شده از قبل و آماده هستند که توی حافظه ROM در BIOS قرار دارند. و برنامه نویس میتونه برای انجام خیلی از کارها از اونا استفاده کنه. در واقع بعد از روشن شدن کامپیوتر این توابع از ROM خونده شده و به RAM منتقل میشه. وقفه ها رو با استفاده از اعداد هگزادسیمال نامگذاری می کنند. که میتونه عددی بین 0 H تا 100H باشه. همچنین به محلی از حافظه که اطلاعت وقفه ها در اون ذخیره میشه "جدول بردار وقفه" یا IVT گفته میشه. یکی از این وقفه ها وقفه شماره 19H هستش که بعد از لود شدن وقفه ها به حافظه به عنوان اولین کار اجرا میشه. وظیفه این وقفه همون چیزیه که تو پست قبلی گفتیم یعنی پیدا کردن و لود و اجرای بوت لودر از سکتور راه انداز دیسک. در ضمن به صورت قراردادی همیشه برنامه بوت لودر بعد از لود شدن در آدرس 7C00H قرار میگیره که بعداً دونستن این نکته به دردمون می خوره. به عنوان توضیح پایانی در مورد وقفه ها باید بگم که وقفه ها معمولاً در برنامه نویسی سطح پایین مورد استفاده قرار می گیرند و یکی از وظیفه های سیستم عامل فراهم کردن توابعی هست که برنامه نوسانی که تو اون سیستم عامل به یه زبون سطح بالا برنامه می نویسند رو از استفاده کردن از وقفه ها بی نیاز کنه. اگه با ویژوال بیسیک برنامه نویسی کرده باشید حتماً میدونید که اونجا اسمی از وقفه ها به میون نیومده ولی وقتی با اسمبلی کار می کنید به وفور باید از وقفه ها استفاده کنید.
نوشتن یک بوت لودر ساده با اسمبلی:
بالاخره به مرحله کدنویسی که میدونم منتظرش بودبد رسیدیم. هچند که این تازه اول راهه و این کد در برابر کدهایی که در آینده قراره بنویسیم تقریباً هیچه ولی باز از هیچی بهتره. این کد کاری که انجام میده در واقع اینه که هیچ کاری انجام نمیده. یک فایل متنی تو Notepad باز کنید و کد زیر رو توش تایپ کنید.
حالا باید کمی در باره این خطوط توضیح بدم. خط اول از راهنمای org استفاده کرده و به اسمبلر می گوید که این کد بعد از لود شدن در آدرس 0x7c00 قرار خواهد گرفت. به یاد دارید که در مورد این موضوع قبلاً توضیح دادیم که همیشه برنامه بوت لودر بعد از لود شدن تو همین آدرس قرار میگیره پس لازمه که این کد رو حتماً اول تمام بوت لودر هایی که مینویسیم بزاریم.
خط دوم به اسمبلر میگه که این برنامه رو به صورت 16 بیتی ترجمه کنه. یعنی اینکه بوت لودر ما یک بوت لودر 16 بیتی هستش. شاید بپرسید مگه قرار نیست که ما یک سیستم عامل 32 بیتی بسازم پس چرا تو حالت 16 بیتی داریم کد مینویسیم. در جواب شما باید بگم که تمام بوت لودر هایی که در تمام دنیا نوشته میشوند اول باید تو مود 16 بیتی باشند و بعد میتونند با اجرای دستوراتی وارد مود 32 بیتی بشوند. یعنی CPU به صورت قراردادی همیشه فرض میکنه که برنامه بوت لودر یک برنامه 16 بیتیه و با حالت 16 بیتی که اصطلاحاً بهش حالت واقعی هم میگن شروع به کار میکنه. فرمان های cli و hlt هم همون طور که برنامه نویسای اسمبلی میدونن به ترتیب وقفه ها رو غیر فعال و Cpu رو متوقف می کنند. که در واقع میشه گفت طبق توضیحات بالا هیچ کار مفیدی نمی کنند.
حتماً یادتون هست که برنامه بوت لودر حتماً باید 512 بایت باشه نه بیشتر نه کمتر ولی این چند خط کد ما 10- 15 بایت بیشتر نمیشه ( البته بعد از ترجمه ). در اسمبلر NASM علامت $ شماره آدرس دستور جاری و $$ شماره آدرس اولین دستور را مشخص میکنند ( باز هم بعد از ترجمه ). از آنجایی که اندازه فایل ترجمه شده باید 512 بایت باشد باید مقداری اطلاعات بی معنی به پایتن فایل ترجمه شده اضافه کنیم تا این مشکل رفع بشه. دستور times که در بالا نوشته شده از بعد از دستور hlt تا بایت 510 رو با مقدار 0 پرمیکنه.
به یاد داشته باشید برای اینکه برنامه شما به عنوان نقطه شروع سیستم یا همون بوت لودر توسط BIOS شناسایی و لود بشه یک شرط دیگه هم وجود داره که تا اینجا بهش اشاره نکرده بدیم. فایل بوت لودر باید دارای امضای مخصوصی باشه تا BIOS بتونه اون رو شناسایی کنه. اون شرط اینه که بایت 511 برابر با 0xAA و بایت 512 برابر با 0x55 باشه. به همین دلیل با دستور times فقط تا بایت 510 رو پر کردیم و دو بایت آخر رو برای امضای بوت لود نگه داشتیم. حالا دیگه توضیحات کامل شده و نوبت مرحله بعدی میرسه.
اسمبل کردن بوت لودر با NASM:
برنامه ای که تو بخش قبلی نوشتید رو توی فایلی به اسم boot.asm ذخیره کنید و توی همون مسیری که برنامه NASM قرار داره قرار بدید. بعد از طریق Command Window به مسیر مربوطه وارد شده و فرمان زیر را اجرا کنید.
این فرمان دارای دو سوییچ است و به ترتیت سویچ –f bin به اسمبلر میگه که فرمت خروجی باید یک فایل باینری باشه و –o هم برای مشخص کردن نام فایل خروجی استفاده میشه. بعد از اجرای این دستور شما باید یک فایل با نام boot.bin دقیقاً با سایز 512 بایت داشته باشید.
1. مقدمه ای در مورد وقفه ها
2. نوشتن یک بوت لودر ساده با اسمبلی
3. اسمبل کردن بوت لودر با NASM
وقفه ها : از اونجایی که داشتن اطلاعات کاملی از وقفه ها برای نوشتن یک سیستم عامل ضروری و اجباریه. و من نمی تونم یه آموزش کامل از این موضوع رو اینجا بزارم، توصیه می کنم اگه اطلاعاتتون تو این زمینه کم هستش مطالعاتتون رو تو این زمینه بیشتر کنید. ولی یه توضیح مختصر درباره وقفه ها برای کسایی که هیچ اطلاعی ندارند میتونه مفید باشه.
وقفه ها در واقع یه سری از توابع نوشته شده از قبل و آماده هستند که توی حافظه ROM در BIOS قرار دارند. و برنامه نویس میتونه برای انجام خیلی از کارها از اونا استفاده کنه. در واقع بعد از روشن شدن کامپیوتر این توابع از ROM خونده شده و به RAM منتقل میشه. وقفه ها رو با استفاده از اعداد هگزادسیمال نامگذاری می کنند. که میتونه عددی بین 0 H تا 100H باشه. همچنین به محلی از حافظه که اطلاعت وقفه ها در اون ذخیره میشه "جدول بردار وقفه" یا IVT گفته میشه. یکی از این وقفه ها وقفه شماره 19H هستش که بعد از لود شدن وقفه ها به حافظه به عنوان اولین کار اجرا میشه. وظیفه این وقفه همون چیزیه که تو پست قبلی گفتیم یعنی پیدا کردن و لود و اجرای بوت لودر از سکتور راه انداز دیسک. در ضمن به صورت قراردادی همیشه برنامه بوت لودر بعد از لود شدن در آدرس 7C00H قرار میگیره که بعداً دونستن این نکته به دردمون می خوره. به عنوان توضیح پایانی در مورد وقفه ها باید بگم که وقفه ها معمولاً در برنامه نویسی سطح پایین مورد استفاده قرار می گیرند و یکی از وظیفه های سیستم عامل فراهم کردن توابعی هست که برنامه نوسانی که تو اون سیستم عامل به یه زبون سطح بالا برنامه می نویسند رو از استفاده کردن از وقفه ها بی نیاز کنه. اگه با ویژوال بیسیک برنامه نویسی کرده باشید حتماً میدونید که اونجا اسمی از وقفه ها به میون نیومده ولی وقتی با اسمبلی کار می کنید به وفور باید از وقفه ها استفاده کنید.
نوشتن یک بوت لودر ساده با اسمبلی:
بالاخره به مرحله کدنویسی که میدونم منتظرش بودبد رسیدیم. هچند که این تازه اول راهه و این کد در برابر کدهایی که در آینده قراره بنویسیم تقریباً هیچه ولی باز از هیچی بهتره. این کد کاری که انجام میده در واقع اینه که هیچ کاری انجام نمیده. یک فایل متنی تو Notepad باز کنید و کد زیر رو توش تایپ کنید.
کد:
Org 0x7c00 bits 16 cli hlt times 510 - ($-$$) db 0 dw 0xAA55
حالا باید کمی در باره این خطوط توضیح بدم. خط اول از راهنمای org استفاده کرده و به اسمبلر می گوید که این کد بعد از لود شدن در آدرس 0x7c00 قرار خواهد گرفت. به یاد دارید که در مورد این موضوع قبلاً توضیح دادیم که همیشه برنامه بوت لودر بعد از لود شدن تو همین آدرس قرار میگیره پس لازمه که این کد رو حتماً اول تمام بوت لودر هایی که مینویسیم بزاریم.
خط دوم به اسمبلر میگه که این برنامه رو به صورت 16 بیتی ترجمه کنه. یعنی اینکه بوت لودر ما یک بوت لودر 16 بیتی هستش. شاید بپرسید مگه قرار نیست که ما یک سیستم عامل 32 بیتی بسازم پس چرا تو حالت 16 بیتی داریم کد مینویسیم. در جواب شما باید بگم که تمام بوت لودر هایی که در تمام دنیا نوشته میشوند اول باید تو مود 16 بیتی باشند و بعد میتونند با اجرای دستوراتی وارد مود 32 بیتی بشوند. یعنی CPU به صورت قراردادی همیشه فرض میکنه که برنامه بوت لودر یک برنامه 16 بیتیه و با حالت 16 بیتی که اصطلاحاً بهش حالت واقعی هم میگن شروع به کار میکنه. فرمان های cli و hlt هم همون طور که برنامه نویسای اسمبلی میدونن به ترتیب وقفه ها رو غیر فعال و Cpu رو متوقف می کنند. که در واقع میشه گفت طبق توضیحات بالا هیچ کار مفیدی نمی کنند.
حتماً یادتون هست که برنامه بوت لودر حتماً باید 512 بایت باشه نه بیشتر نه کمتر ولی این چند خط کد ما 10- 15 بایت بیشتر نمیشه ( البته بعد از ترجمه ). در اسمبلر NASM علامت $ شماره آدرس دستور جاری و $$ شماره آدرس اولین دستور را مشخص میکنند ( باز هم بعد از ترجمه ). از آنجایی که اندازه فایل ترجمه شده باید 512 بایت باشد باید مقداری اطلاعات بی معنی به پایتن فایل ترجمه شده اضافه کنیم تا این مشکل رفع بشه. دستور times که در بالا نوشته شده از بعد از دستور hlt تا بایت 510 رو با مقدار 0 پرمیکنه.
به یاد داشته باشید برای اینکه برنامه شما به عنوان نقطه شروع سیستم یا همون بوت لودر توسط BIOS شناسایی و لود بشه یک شرط دیگه هم وجود داره که تا اینجا بهش اشاره نکرده بدیم. فایل بوت لودر باید دارای امضای مخصوصی باشه تا BIOS بتونه اون رو شناسایی کنه. اون شرط اینه که بایت 511 برابر با 0xAA و بایت 512 برابر با 0x55 باشه. به همین دلیل با دستور times فقط تا بایت 510 رو پر کردیم و دو بایت آخر رو برای امضای بوت لود نگه داشتیم. حالا دیگه توضیحات کامل شده و نوبت مرحله بعدی میرسه.
اسمبل کردن بوت لودر با NASM:
برنامه ای که تو بخش قبلی نوشتید رو توی فایلی به اسم boot.asm ذخیره کنید و توی همون مسیری که برنامه NASM قرار داره قرار بدید. بعد از طریق Command Window به مسیر مربوطه وارد شده و فرمان زیر را اجرا کنید.
کد:
nasm -f bin boot.asm -o boot.bin
این فرمان دارای دو سوییچ است و به ترتیت سویچ –f bin به اسمبلر میگه که فرمت خروجی باید یک فایل باینری باشه و –o هم برای مشخص کردن نام فایل خروجی استفاده میشه. بعد از اجرای این دستور شما باید یک فایل با نام boot.bin دقیقاً با سایز 512 بایت داشته باشید.
دیدگاه