منبع اصلی نوشتار زیر در این لینک قرار دارد

نوشتن یک سیستم عامل ساده – قسمت دوم

در مقاله قبلی، در مورد نمایش یک حرف روی مانیتور صحبت شد. اما یک حرف کافی نیست. حتی نمیشه به صورت حرف به حرف کلمات و جملات رو نشون داد چون واقعا کار سختیه. ما میخوایم یک پیغام (مثل Hello World) رو موقع بوت شدن سیستم عاملمون شاهد باشیم. پس باید چه کنیم؟ یک راه حل اینه که از یک ویژگی ای در زبان مورد نظر (اینجا اسمبلی) استفاده کنیم که بتونه یک رشته رو چاپ کنه. طبیعتا اسمبلی به طور پیشفرض دستوری مثل cout نداره و ما مجبوریم که خودمون اون رو به cout بیاریم. در این قسمت از مقالات «نوشتن یک سیستم عامل ساده» به این میپردازیم که چطور سیستم عامل ۱۶ بیتی ما، یک یا چند جمله رو نشونمون بده! در این قسمت علاوه بر رجیستر AX از سایر رجیستر ها هم استفاده خواهیم کرد. ممکنه بپرسید چرا؟ جواب سوالتون رو توی متن میگیرید!

خب فایل my16bitos.asm رو باز کنید. کل محتواش رو پاک کنید و این رو جایگزینش کنید :

کد   
org 0x7c00
bits 16
 
mov ax, 0
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7c00
 
mov si, welcome 
call print_string 
 
mov si, about
call print_string
 
welcome db  'Welcome to my OS', 0x0d, 0x0a, 0
about db  'Written in 16-bit real mode', 0x0d, 0x0a, 0
 
print_string:
 lodsb
 or al, al
 jz .done 
 
 mov ah, 0x0e
 int 0x10
 
  jmp print_string
 
 
 .done:
   ret
 
times 510-($-$$) db 0
dw 0xaa55

دیدید ؟ کد خیلی طولانی تر شده نسبت به قبل. طبیعیه چون که ما یه تابع تعریف کردیم و از یه سری چیزای جدید هم استفاده کردیم. خب آماده اید؟ میریم که بخش به بخش سیستم عامل کوچولوی خودمون رو بررسی کنیم!

کد   
org 0x7c00
bits 16

این قسمت، برای اینه که اولا ، اسمبلر آدرس ها رو بفهمه، ثانیا بفهمه که کد چند بیتیه. در آینده کد ما ۳۲ بیت خواهد شد و این بخش هم تغییر خواهد کرد. ولی فعلا تا آموزشهای بعدی همین برنامه رو داریم.

کد   
mov ax, 0
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7c00

این قسمت از کدمون هم مقدار صفر رو توی رجیستر AX میذاره و سپس اون رو به Data Segment, Extra Segment و Stack Segment منتقل میکنه (توجه کنید مستقیما نمیتونیم مقداری رو درون این رجیستر ها بذاریم. پس اول مقدار رو میذاریم توی AX سپس با MOV یکی یکی منتقل میکنیم). در آخر هم مقدار 7C00 هگزا دسیمال رو توی Stack Pointer قرار میدیم (استک از این آدرس شروع میکنه و میاد پایین).  این بخش داره مقدمات اجرای سیستم عامل ما رو فراهم میکنه.

بعد از اونا میرسیم به این بخش :

کد   
mov si, welcome 
call print_string 
 
mov si, about
call print_string
 
welcome db  'Welcome to my OS', 0x0d, 0x0a, 0
about db  'Written in 16-bit real mode', 0x0d, 0x0a, 0

این قسمت تقریبا ساده ترین قسمت برنامست. اومدیم welcome و about که دو رشته هستند رو ریختیم توی Source Index و سپس تابع print_string که کارش چاپ رشته هست هم صدا زدیم. با دستور db هم گفتیم که چه رشته هایی رو مد نظر داریم که چاپ شن. اون اعداد هگزاسیمال بعد از متغیر ها هم معادل New Line هستند (مثلا مقدار n در دستورات بک اسلش در C ).

بعد از این جنگولک بازیا ( 😀 ) میرسیم به کار اصلیمون یعنی نوشتن تابع print_string . این تابع نسبتا سادس ولی خب نیاز به توضیح داره چون دستوراتی رو استفاده کردیم که توی مطلب قبلی نبودن :

کد   
print_string:
 lodsb
 or al, al
 jz .done 
 
 mov ah, 0x0e
 int 0x10
 
  jmp print_string
 
 
 .done:
   ret

خب اول اومدیم اسم تابع رو گذاشتیم print_string (شما میتونید هرچیزی دلتون میخواد بذارید، مثلا دوستی ممکنه بذاره cout که براش ملموس تره و …). بیایم ببینیم خط به خط تابع چه میکنه؟

اون lodsb یک بایت رو از SI میخونه ، بعد رجیستر AL با خودش از نظر منطقی OR میشه. در نهایت اگر نتیجه صفر شد میره به done که done هم همونطور که می بینید داره return میکنه و از تابع خارج میشه. اگر جواب صفر نشه، مقدار 0e هگزا دسیمال وارد AH میشه و سپس وقفه 10 هگزادسیمال که یکی از وقفه های بایوس هست اجرا میشه. در واقع 0e یکی از تابع های وقفه مورد نظر ماست. بعد از اون پرش رخ میده به print_string. در واقع ما یک حلقه نوشتیم که به تعداد کرکتر های رشتمون، تکرار میشه و رشته رو تکرار میکنه.

در نهایت هم باید به اسمبلر بفهمونیم که برناممون یک Boot Sector عه پس طبیعتا از این قطعه کد استفاده میکنیم که در مطلب قبلی توضیحش دادم :

کد   
times 510-($-$$) db 0
dw 0xaa55

خب الان یک سیستم عاملی داریم که میتونه یک رشته چاپ کنه. ولی هنوز نمیتونه چیزی رو از کاربر بگیره و بخونه. این مورد میره برای آموزش های بعدی. فعلا بیاید این کد رو توی ویرچوال باکس اجرا کنیم! برای اجرای این سیستم عامل کد های زیر رو به ترتیب توی ترمینال اجرا کنید :

کد   
nasm -f bin -o my16bitos.bin my16bitos.asm
dd if=my16bitos.bin of=my16bitos.img

بعد یک ماشین مجازی توی ویرچوال باکس ایجاد کنید، یک Floppy Controller بسازید و اولویت بوت رو بهش بدید. سپس img رو بدید به فلاپی کنترلر و سپس ماشین رو روشن کنید. باید چنین صحنه ای رو مشاهده کنید :

 

os

تبریک! شما تقریبا نصف بیشتر راه رو رفتید! در ادامه هم میرسیم به باقی ماجرا و نوشتن prompt و این چیزا!

موفق باشید :)

FacebookTwitterGoogle+Share



برچسب ها : , , , , , ,