PDA

View Full Version : سوال: GDT و چند سوال درباره رجیستر ها



DEATH HUNTER
سه شنبه 23 فروردین 1390, 12:10 عصر
1-اگه ما دو تا GDT با بیس یکسان داشته باشیم به طوری که تفاوت اون ها فقط در نوع باشه یکی code descriptor و دیگری data descriptor آیا هر دو، یک سگمنت محاسبه می شوند یا خیر هر کدام سگمنت مجزا از هم هستند؟

2-آیا مقدار دهی به SP و CS و IP خود به خود انجام میشود؟مثلا چرا زمانی که از Real Mode به Protected Mode مد می رویم حتما باید اشاره گر به Descriptor Table را در CS قرار دهیم؟در صورتی که در حالت عادی ما کاری به cs نداریم؟
jmp Descriptore Base:Code
آقا پویا گفتن این جا بپرسم تا هم خودم و هم دوستان استفاده کنند؟

pswin.pooya
چهارشنبه 24 فروردین 1390, 23:07 عصر
۱. بله میشه GDT ها رو overwrite کرد.

۲. این ثابتها رو نمیشه به صورت مستقیم بار کرد اما راههای میانبر وجود داره مثلا برای IP میتونین یه jmp بزنین و ... . من بعدا توی یه تاپیک در مورد ثباتهای x86 یه مقاله داخل سایت میذازم.

pswin.pooya
جمعه 09 اردیبهشت 1390, 01:19 صبح
سلام
من یه تست کوچولو زدم. (البته نه چندان):
شما به غیر از ثباتهای کنرلی و ip و eip و همینطور فلگها تقریبا بقیه ثباتها رو می تونید به صورت مستقیم بار کنید‌(یعنی از دستور mov استفاده کنید)

در مورد CS باید بگم که شما شماره مدخلی رو که توی GDT تعریف کردین رو داخلش قرار میدید تا cpu بفهمه بیس کد شما چیه (کجا قرار داره) و همینطور مال مدخل دیتا رو توی DS. البته این دقیقا مقدار اندیس نیست و از رابطه زیر بدست میاد:‌

8 * index
مثلا برای مدخل سوم داریم 0x10 یا همون ۱۶ که توی کد من آدرس توصیفگر دیتای هسته هست که با توجه به اون مقدار تمامی ثباتها به اون ست میشه (توجه كنيد كه مدخل اول يا انديس صفر هميشه Null هست):


mov ax, 0x10 ; 0x10 is the offset in the GDT to kernel data segment
mov ds, ax ; Load all data segment selectors
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax

حالا ما باید cs و ip رو ست کنیم. برای اینکار یه راه راحت به اسم jmp وجود داره. تنها کاری که کافیه بکنیم اینه که یه پرش به این آدرس انجام بدیم:


jmp 0x08:.flush!
.flush:

0x8 همون مدخل اول من یا اولین توصیفگر من هست که مربوط به توصیفگر کد هست.

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


// set default code descriptor (kernel mode)
gdtSetDescriptor (1,0,0xffffffff,
GDT_DESC_READWRITE | GDT_DESC_EXEC_CODE | GDT_DESC_CODEDATA | GDT_DESC_MEMORY,
GDT_GRAND_4K | GDT_GRAND_32BIT | GDT_GRAND_LIMITHI_MASK);

// set default data descriptor (kernel mode)
gdtSetDescriptor (2,0,0xffffffff,
GDT_DESC_READWRITE| GDT_DESC_CODEDATA| GDT_DESC_MEMORY,
GDT_GRAND_4K | GDT_GRAND_32BIT | GDT_GRAND_LIMITHI_MASK);

// set default code descriptor (user mode)
gdtSetDescriptor (3,0,0xffffffff,
GDT_DESC_READWRITE | GDT_DESC_EXEC_CODE | GDT_DESC_CODEDATA | GDT_DESC_MEMORY | GDT_DESC_RING3,
GDT_GRAND_4K | GDT_GRAND_32BIT | GDT_GRAND_LIMITHI_MASK);

// set default data descriptor(user mode)
gdtSetDescriptor (4,0,0xffffffff,
GDT_DESC_READWRITE| GDT_DESC_CODEDATA| GDT_DESC_MEMORY | GDT_DESC_RING3 ,
GDT_GRAND_4K | GDT_GRAND_32BIT | GDT_GRAND_LIMITHI_MASK);


جدول GDT یه جدول برای توصیف حافظه هست. از اونجا که شما دارین به حالت محافظت شده سوئیچ می کنید. باید حافظه خودتون و محدودیتهای دسترسی رو هم مشخص کنید. از طرف دیگه توی این حالت معمولا حافظه مجازی مهم هست و دو راه برای حافظه مجازی داریم:

۱. استفاده از قطعاتی که با GDT توصیف میشن.
۲. استفاده از صفحه بندی.

راه اول به سرعت در حال انقراض هست و نمیشه اون رو به جزء موارد نادر جایی دیگه دید اما راه دوم هم به سرعت در حال همه گیر شدن... .