به نام خداوند بخشنده و مهربان!
سلام عرض میکنم خدمت شما دوستان عزیز و هموطنان گرامی! امیدوارم حالتون خوب باشه!
بعد از چند وقتی دوباره تصمیم گرفتم قسمت بعدی آموزش ساخت سیستم عامل رو براتون آماده کنم! امیدوارم به دردتون بخوره و ما رو دعا کنید!
خوب در جلسه قبل جدول توصیفگر سراسری یا GDT رو خدمتتون تدریس کردیم! و نگاهی به قالب اون انداختیم. یک مثال زدیم و اون مثال رو تجزیه و تحلیل کردیم. گفتیم جدول توصیفگر سراسری شامل سه واصف (توصیفگر) هست. واصف NULL یا پوچ، واصف کد و واصف دیتا. همچنین گفتیم علاوه بر جدول توصیفگر سراسری GDT یه چیز دیگه هم به نام جدول توصیفگر وقفه یا IDT داریم که در مود 32 بیتی برای وقفه ها و استثنا ها استفاده میشه! و در نهایت در جلسه قبل وارد مود 32 بیتی شدیم!
در این قسمت میخوایم خط A20 رو فعال کنیم!
خط A20 یک گیت (دروازه) فیزیکی هست که به یکی از پایه های یکی از سخت افزار ها وصل هست (میتونید سرچ کنید یا از توی همین سایت منبع از روش بخونید) که وقتی ما اونو فعال کنیم باعث میشه که دیگه آدرس دهی ما به 20 خط یا همون 1 مگابایت محدود نباشه و آدرس دهی ما 32 بیتی بشه! بنابراین ما برای دسترسی به چهار گیگ فضا نیاز به فعال کردن A20 داریم! و قصد داریم در این جلسه این کار رو انجام بدیم!
ببینید ما یه موضوعی داریم به نام برنامه نویسی مستقیم سخت افزار که یه چیز تقریبا مهمی هست. من این سایت منبع رو پیشنهاد میکنم یه نگاهی بندازید! (کلیک کنید)
ما حالا نیاز داریم با سخت افزار به طور مستقیم ارتباط برقرار کنیم و از طریق دو دستور خاص IN و OUT اینکار رو انجام میدیم!
راستش یه میکروکنترلری وجود داره به نام Intel 8042 که به کیبورد ما وصل هست و کیبورد رو کنترل میکنه یعنی مثلا کلیدی رو که زدیم رو سیگنالش رو میگیره و به CPU میگه چه کلیدی زده شده! اون خط A20 ما با این میکروکنترلر در ارتباط هست. یعنی ما برای اینکه خط A20 رو فعال کنیم باید با 8042 ارتباط برقرار کنیم!
ببینید وقتی که BIOS POST اجرا میشه به هر دیوایس یا سخت افزار از طریق کنترلر ورودی و خروجی یه آدرس تعیین میکنه که ما برای اینکه بتونیم به اون سخت افزار دسترسی داشته باشیم باید بدونیم اون آدرسی که BIOS براش گذاشته چیه؟ به همین دلیل یه جدولی وجو داره که آدرس همه این پورت ها رو نشون میده! اون جدول رو در زیر براتون آوردم!
Default x86 Port Address Assignments | ||||
---|---|---|---|---|
Address Range | First QWORD | Second QWORD | Third QWORD | Fourth QWORD |
0x000-0x00F | DMA Controller Channels 0-3 | |||
0x010-0x01F | System Use | |||
0x020-0x02F | Interrupt Controller 1 | System Use | ||
0x030-0x03F | System Use | |||
0x040-0x04F | System Timers | System Use | ||
0x050-0x05F | System Use | |||
0x060-0x06F | Keyboard/PS2 Moude (Port 0x60) Speaker (0x61) |
Keyboard/PS2 Mouse (0x64) | System Use | |
0x070-0x07F | RTC/CMOS/NMI (0x70, 0x71) | DMA Controller Channels 0-3 | ||
0x080-0x08F | DMA Page Register 0-2 (0x81 - 0x83) | DMA Page Register 3 (0x87) | DMA Page Register 4-6 (0x89-0x8B) | DMA Page Register 7 (0x8F) |
0x090-0x09F | System Use | |||
0x0A0-0x0AF | Interrupt Controller 2 (0xA0-0xA1) | System Use | ||
0x0B0-0x0BF | System Use | |||
0x0C0-0x0CF | DMA Controller Channels 4-7 (0x0C0-0x0DF), bytes 1-16 | |||
0x0D0-0x0DF | DMA Controller Channels 4-7 (0x0C0-0x0DF), bytes 16-32 | |||
0x0E0-0x0EF | System Use | |||
0x0F0-0x0FF | Floating Point Unit (FPU/NPU/Mah Copprocessor) | |||
0x100-0x10F | System Use | |||
0x110-0x11F | System Use | |||
0x120-0x12F | System Use | |||
0x130-0x13F | SCSI Host Adapter (0x130-0x14F), bytes 1-16 | |||
0x140-0x14F | SCSI Host Adapter (0x130-0x14F), bytes 17-32 | SCSI Host Adapter (0x140-0x15F), bytes 1-16 | ||
0x150-0x15F | SCSI Host Adapter (0x140-0x15F), bytes 17-32 | |||
0x160-0x16F | System Use | Quaternary IDE Controller, master slave | ||
0x170-0x17F | Secondary IDE Controller, Master drive | System Use | ||
0x180-0x18F | System Use | |||
0x190-0x19F | System Use | |||
0x1A0-0x1AF | System Use | |||
0x1B0-0x1BF | System Use | |||
0x1C0-0x1CF | System Use | |||
0x1D0-0x1DF | System Use | |||
0x1E0-0x1EF | System Use | Tertiary IDE Controller, master slave | ||
0x1F0-0x1FF | Primary IDE Controller, master slave | System Use | ||
0x200-0x20F | Joystick Port | System Use | ||
0x210-0x21F | System Use | |||
0x220-0x22F | ||||
Sound Card | ||||
Non-NE2000 Network Card | System Use | |||
0x230-0x23F | SCSI Host Adapter (0x220-0x23F), bytes 17-32) | |||
0x240-0x24F | ||||
Sound Card | ||||
Non-NE2000 Network Card | System Use | |||
NE2000 Network Card (0x240-0x25F) Bytes 1-16 | ||||
0x250-0x25F | NE2000 Network Card (0x240-0x25F) Bytes 17-32 | |||
0x260-0x26F | ||||
Sound Card | ||||
Non-NE2000 Network Card | System Use | |||
NE2000 Network Card (0x240-0x27F) Bytes 1-16 | ||||
0x270-0x27F | ||||
System Use | Plug and Play System Devices | LPT2 - Second Parallel Port | ||
System Use | LPT3 - Third Parallel Port (Monochrome Systems) | |||
NE2000 Network Card (0x260-0x27F) Bytes 17-32 | ||||
0x280-0x28F | ||||
Sound Card | ||||
Non NE2000 Network Card | System Use | |||
NE2000 Network Card (0x280-0x29F) Bytes 1-16 | ||||
0x290-0x29F | NE2000 Network Card (0x280-0x29F) Bytes 17-32 | |||
0x2A0-0x2AF | ||||
Non NE2000 Network Card | System Use | |||
NE2000 Network Card (0x280-0x29F) Bytes 1-16 | ||||
0x2B0-0x2BF | NE2000 Network Card (0x280-0x29F) Bytes 17-32 | |||
0x2C0-0x2CF | System Use | |||
0x2D0-0x2DF | System Use | |||
0x2E0-0x2EF | System Use | COM4 - Fourth Serial Port | ||
0x2F0-0x2FF | System Use | COM2 - Second Serial Port | ||
0x300-0x30F | ||||
Sound Card / MIDI Port | System Use | |||
Non NE2000 Network Card | System Use | |||
NE2000 Network Card (0x300-0x31F) Bytes 1-16 | ||||
0x310-0x31F | NE2000 Network Card (0x300-0x32F) Bytes 17-32 | |||
0x320-0x32F | ||||
Sound Card / MIDI Port (0x330, 0x331) | System Use | |||
NE2000 Network Card (0x300-0x31F) Bytes 17-32 | ||||
SCSI Host Adapter (0x330-0x34F) Bytes 1-16 | ||||
0x330-0x33F | ||||
Sound Card / MIDI Port | System Use | |||
Non NE2000 Network Card | System Use | |||
NE2000 Network Card (0x300-0x31F) Bytes 1-16 | ||||
0x340-0x34F | ||||
SCSI Host Adapter (0x330-0x34F) Bytes 17-32 | ||||
SCSI Host Adapter (0x340-0x35F) Bytes 1-16 | ||||
Non NE2000 Network Card | System Use | |||
NE2000 Network Card (0x340-0x35F) Bytes 1-16 | ||||
0x350-0x35F | ||||
SCSI Host Adapter (0x340-0x35F) Bytes 17-32 | ||||
NE2000 Network Card (0x300-0x31F) Bytes 1-16 | ||||
0x360-0x36F | ||||
Tape Accelerator Card (0x360) | System Use | Quaternary IDE Controller (Slave Drive)(0x36E-0x36F) | ||
Non NE2000 Network Card | System Use | |||
NE2000 Network Card (0x300-0x31F) Bytes 1-16 | ||||
0x370-0x37F | ||||
Tape Accelerator Card (0x370) | Secondary IDE Controller (Slave Drive) | LPT1 - First Parallel Port (Color systems) | ||
System Use | LPT2 - Second Parallel Port (Monochrome Systems) | |||
NE2000 Network Card (0x360-0x37F) Bytes 1-16 | ||||
0x380-0x38F | System Use | Sound Card (FM Synthesizer) | System Use | |
0x390-0x39F | System Use | |||
0x3A0-0x3AF | System Use | |||
0x3B0-0x3BF | VGA/Monochrome Video | LPT1 - First Parallel Port (Monochrome Systems) | ||
0x3C0-0x3CF | VGA/CGA Video | |||
0x3D0-0x3DF | VGA/CGA Video | |||
0x3E0-0x3EF | ||||
Tape Accelerator Card (0x370) | System Use | COM3 - Third Serial Port | ||
System Use | Tertiary IDE Controller (Slave Drive)(0x3EE-0x3EF) | |||
0x3F0-0x3FF | ||||
Floppy Disk Controller | COM1 - First Serial Port | |||
Tape Accelerator Card (0x3F0) | Primary IDE Controller (Slave Drive)(0x3F6-0x3F7) | System Use |
This table is not complete, and hopefully has no errors in it. I will add to this table as time goes on, and more devices are developed.
ب
خوب اگه دقت کنید میبینید که برای کیبورد توی جدول بالا آدرس 0X60 رو نوشته. حالا ما میتونیم با دستور مخصوص IN و OUT با کیبورد ارتباط برقرار کنیم
یه مثال میزنم!
in al, 0x60 ; get byte from 8042 microcontroller input register
کد بالا مقداری رو از میکروکنترلر 8042 میگیره و در al قرار میده!
» فعال کردن A20
راه های فعال کردن A20 خیلی زیاده و ممکنه همه شون روی یه کامپیوتر جواب نده. منظورم اینه که ممکنه یه راه برای فعال کردن A20 وجود داشته باشه که روی کامپیوتر من کار کنه ولی روی کامپیوتر شما کار نکنه!
ولی به هرحال ما چندتا راهش رو براتون میگیم!
راه اول: از طریق System Control Port A
این راه آسون ترین و ساده ترین راه ممکن هست. ما میتونیم توی بعضی از کامپیوتر ها از طریق کنترلر ورودی و خروجی 0x92 خط A20 رو فعال کنیم! چند بیت پایین میتونیم استفاده کنیم!
- Bit 0 - Setting to 1 causes a fast reset (Used to switch back to real mode)
- Bit 1 - 0: disable A20; 1: enable A20
- Bit 2 - Manufacturer defined
- Bit 3 - power on password bytes (CMOS bytes 0x38-0x3f or 0x36-0x3f). 0: accessible, 1: inaccessible
- Bits 4-5 - Manufacturer defined
- Bits 6-7 - 00: HDD activity LED off; any other value is "on"
خوب همونطور که میبینید بیت 1 یا همون بیت دوم برای فعال کردن A20 استفاده میشه پس ما میتونیم این بیت رو فعال کنیم تا A20 فعال بشه! خوب خیلی آسون با استفاده از دستور OUT اینکار رو انجام میدیم!
mov al, 2 ; set bit 2 (enable a20)
out 0x92, al
کار های دیگه هم ما میتونیم با این پورت انجام بدیم. مثل، مثال زیر
mov al, 1 ; set bit 1 (fast reset)
out 0x92, al
این روش روی بعضی از ماشین های مجازی سازی مثل Bochs (پیشنهاد میکنم این برنامه رو هم دانلود و نصب کنید و از این به بعد از اون استفاده کنید) به خوبی جواب میده!
روش دوم: از طریق BIOS
این روش از طریق bios خط A20 رو فعال میکنه که میتونید برید توی مطلب اصلی از اینجا بخونید!
روش سوم : کنترلر کیبورد
در این روش باید با میکروکنترلر 8043 که بالا درباره اش حرف زدیم، ارتباط برقرار کنیم! بنابراین باید قبلش با برنامه نویسی سخت افزار کمی آشنا بشیم!
نقشه پورت
ببینید باید ما با نقشه ی این کنترلر آشنا باشیم تا بتونیم با اون ارتباط برقرار کنیم. نقشه اون به شکل زیره
Port Mapping | ||
---|---|---|
Port | Read/Write | Descripton |
0x60 | Read | Read Input Buffer |
0x60 | Write | Write Output Buffer |
0x64 | Read | Read Status Register |
0x64 | Write | Send Command to controller |
همونطور که میبینید از پورت 0X60 استفاده شده.ما میتونیم با نوشتن در پورت 0X64 یه دستور رو برای این میکروکنترلر ارسال کنیم و اگه این دستور یه پارامتر هم داشته باشه میتونیم اونو از طریق پورت 0X60 بفرستیم. بعد میتونیم پیامی که میکروکنترلر برامون میفرسته رو از طریق پورت 0X60 بخونیم!
راستش سرعت این میکروکنترلر خیلی از سرعت CPU ما پایین تر هست بنابراین دیرتر به درخواست ما پاسخ میده. برای اینکه ما درست بتونیم کار کنیم باید منتظر بمونیم تا ببینیم کی پاسخ میده! برای اینکار باید به وضعیت میکروکنترلر نگاه کنیم ببینیم آیا پاسخ داد؟ وقتی پاسخ داد بریم اونو بخونیم! حالا از کجا وضعیت میکروکنترلر رو پیدا کنیم؟
به جدول زیر یه نگاهی بندازید! ما میتویم این جدول رو با خوندن از پورت 0X64 بدست بیاریم
- Bit 0: Output Buffer Status
- 0: Output buffer empty, dont read yet
- 1: Output buffer full, please read me :)
- Bit 1: Input Buffer Status
- 0: Input buffer empty, can be written
- 1: Input buffer full, dont write yet
- Bit 2: System flag
- 0: Set after power on reset
- 1: Set after successfull completion of the keyboard controllers self-test (Basic Assurance Test, BAT)
- Bit 3: Command Data
- 0: Last write to input buffer was data (via port 0x60)
- 1: Last write to input buffer was a command (via port 0x64)
- Bit 4: Keyboard Locked
- 0: Locked
- 1: Not locked
- Bit 5: Auxiliary Output buffer full
- PS/2 Systems:
- 0: Determins if read from port 0x60 is valid If valid, 0=Keyboard data
- 1: Mouse data, only if you can read from port 0x60
- AT Systems:
- 0: OK flag
- 1: Timeout on transmission from keyboard controller to keyboard. This may indicate no keyboard is present.
- Bit 6: Timeout
- 0: OK flag
- 1: Timeout
- PS/2:
- General Timeout
- AT:
- Timeout on transmission from keyboard to keyboard controller. Possibly parity error (In which case both bits 6 and 7 are set)
- Bit 7: Parity error
- 0: OK flag, no error
- 1: Parity error with last byte
خوب چیز های مهم زیاد داره که من اونا رو بزرگ نوشتم!
فک کنید ما یه دستور به میکروکنترلر ارسال کردیم. حالا باید منتظر جواب بمونیم. کد اون به شکل زیر میشه که داره پورت رو میخونه تا ببینه آیا میکروکنترلر جواب داده هنوز یا نه!
wait_input:
in al,0x64 ; read status register
test al,2 ; test bit 2 (Input buffer status)
jnz wait_input ; jump if its not 0 (not empty) to continue waiting
ارسال دستور به میکروکنترلر 8043
خوب حالا وقت اون رسیده تا به میکروکنترلر مون یه دستور بفرستیم که A20 رو فعال کن! اگه برگردید و به جدول بالا دوباره نگاه کنید میبینید برای ارسال دستور باید از پورت 0X64 استفاده کنیم!
این میکروکنترلر یا کیبورد کنترلر خیلی دستور داره که ما میتونیم براش بفرستیم ولی لازم نداریم همه رو بدونیم چون ما فعلا میخوایم خط A20 رو فعال کنیم. جدول زیر کمی از دستورات این میکروکنترلر رو نشون میده!
Keyboard Controller Commands | |
---|---|
Keyboard Command | Descripton |
0x20 | Read Keyboard Controller Command Byte |
0x60 | Write Keyboard Controller Command Byte |
0xAA | Self Test |
0xAB | Interface Test |
0xAD | Disable Keyboard |
0xAE | Enable Keyboard |
0xC0 | Read Input Port |
0xD0 | Read Output Port |
0xD1 | Write Output Port |
0xDD | Enable A20 Address Line |
0xDF | Disable A20 Address Line |
0xE0 | Read Test Inputs |
0xFE | System Reset |
Mouse Command | Descripton |
0xA7 | Disable Mouse Port |
0xA8 | Enable Mouse Port |
0xA9 | Test Mouse Port |
0xD4 | Write to mouse |
اگه به جدول بالا دقت کنید بایت 0XDD و 0XDF برای فعال کردن و غیر فعال کردن خط A20 استفاده میشه!
بنابراین با کد زیر میتونیم به این بایت دسترسی پیدا کنیم!
; Method 3.1: Enables A20 through keyboard controller
mov al, 0xdd ; command 0xdd: enable a20
out 0x64, al ; send command to controller
یه راه دیگه هم از طریق همین جدول بالا وجود داره که میتونیم اون راه هم انجام بدیم!
برای راه دوم باید از دوبایت 0XD0 و 0XD1 در جدول بالا استفاده کنیم برای آشنایی با این مورد هم میتونید به سایت منبع اصلی سر بزنید و قسمت Method 3.2: Enabling A20 through Output Port رو مطالعه کنید! (اینجا کلیک کنید)
خوب کد همه موارد بالا به صورت کامل میتونید از لینک زیر دریافت کنید!
دانلود کنید!
خیلی مطالب بیشتری توی سایت منبع وجود داره! تاکید اکید میکنم حتما برید از سایت منبع هم بخونید که خیلی بیشتر میفهمید و پیشرفت میکنید. انشالله...
خوب این قسمت هم به پایان رسید. امیدوارم مفید واقع شده باشه!
فعلا!
یا علی مدد....!