محاكاة Linus Torvalds: قم بإنشاء نظام التشغيل الخاص بك من البداية (IV)

أهلا بكم من جديد في هذه السلسلة من التدوينات بعنوان "محاكاة لينوس تورفالدس". اليوم سنرى GDT. أولا علينا أن نرى ما هو GDT. حسب ويكيبيديا:

جدول الواصف العام or GDT هي بنية البيانات المستخدمة من قبل إنتل x86- معالجات عائلية تبدأ بـ 80286 من أجل تحديد خصائص مناطق الذاكرة المختلفة المستخدمة أثناء تنفيذ البرنامج ، بما في ذلك العنوان الأساسي والحجم وامتيازات الوصول مثل قابلية التنفيذ وقابلية الكتابة

ما يُترجم سيكون جدول واصف عالمي ، وهي بنية بيانات مستخدمة في معالجات Intel x86 منذ 80286 لتحديد خصائص مناطق الذاكرة المختلفة المستخدمة أثناء تنفيذ البرنامج.

باختصار ، إذا كنا نستخدم معالج Intel x86 ، فيجب علينا تحديد GDT للاستخدام الصحيح للذاكرة. لن نقوم بالكثير من التعقيد وسنقوم بتعريف 3 مداخل في الجدول:

  • إدخال فارغ ، مطلوب لجميع الجداول.
  • تذكرة للقسم البيانات، سوف نستخدم الحد الأقصى ، والذي يبلغ 32 جيجابايت في 4 بت.
  • تذكرة للقسم الكود، سوف نستخدم الحد الأقصى ، والذي يبلغ 32 جيجابايت في 4 بت.

كما ترى ، ستستخدم البيانات والرمز نفس المساحة. حسنًا ، نحن الآن بصدد تنفيذه. لهذا سوف نستخدم هيكلين ، الأول سيكون مسؤولاً عن احتواء مؤشر للبيانات الحقيقية لـ GDT الخاص بنا. والثاني سيكون مصفوفة بإدخالات GDT. دعونا نحددها أولا

struct Entry{
uint16_t limit_low;
uint16_t base_low;
uint8_t base_middle;
uint8_t access;
uint8_t granularity;
uint8_t base_high;
} __attribute__((packed));
struct Ptr{
uint16_t limit;
uint32_t base;
} __attribute__((packed));

ربما لاحظت __ سمة __ غريبة ((معبأة)) في نهاية الهياكل. هذا يخبر دول مجلس التعاون الخليجي بعدم تحسين الهياكل لأن ما نريده هو تمرير البيانات كما هي إلى المعالج. الآن سنقوم بعمل وظيفة لتثبيت GDT. قبل أن نعلن عن الهياكل ، سنبدأ الآن في تهيئتها.

struct ND::GDT::Entry gdt[3];
struct ND::GDT::Ptr gp;
void ND::GDT::Install()
{
gp.limit=(sizeof(struct ND::GDT::Entry)*3)-1;
gp.base=(uint32_t)&gdt;
}

لذلك علينا أن نبني المؤشر الذي ينتقل إلى جدول 3 مدخلات.

إذا جمعت باستخدام 64 بت ، فمن المرجح أن تفشل هنا. هذا لأن المؤشرات على أنظمة 64 بت هي بوضوح 64 بت ونستخدم أنواع 32 بت هنا. قد يساعد استخدام الخيار -m32 في الوقت الحالي
الآن نحدد وظيفة مشتركة لوضع البيانات في المدخلات

void ND::GDT::SetGate(int num, uint32_t base, uint32_t limit, uint8_t access,uint8_t gran)
{
gdt[num].base_low=(base & 0xFFFF);
gdt[num].base_middle=(base >> 16) & 0xFF;
gdt[num].base_high=(base >> 24) & 0xFF;
gdt[num].limit_low=(limit & 0xFFFF);
gdt[num].granularity=(limit >> 16) & 0x0F;
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access=access;
}

ونسميها 3 مرات من وظيفة التثبيت

ND::GDT::SetGate(0,0,0,0,0); /* NULL segmente entry */
ND::GDT::SetGate(1,0,0xFFFFFFFF,0x9A,0xCF); /* 4 GiB for Code Segment */
ND::GDT::SetGate(2,0,0xFFFFFFFF,0x92,0xCF); /* 4 GiB for Data segment */

أخيرًا ، يجب أن نخبر المعالج أن لدينا GDT ، حتى يتمكن من تحميله ، وفي حالتنا عند تحميل النواة باستخدام GRUB ، قم بالكتابة فوق GRUB GDT. لتحميل GDT هناك تعليمات في ASM تسمى lgdt (أو lgdtl اعتمادًا على البنية) ، سنستخدمها.

asm volatile("lgdtl (gp)");
asm volatile(
"movw $0x10, %ax \n"
"movw %ax, %ds \n"
"movw %ax, %es \n"
"movw %ax, %fs \n"
"movw %ax, %gs \n"
"movw %ax, %ss \n"
"ljmp $0x08, $next \n"
"next: \n"
);

حسنًا ، بمجرد الانتهاء من هذا ، سيحصل نظامنا بالفعل على GDT. في الفصل التالي سنرى IDT ، وهو جدول مشابه جدًا لـ GDT ولكن مع انقطاعات. لقد وضعت بعض رسائل الحالة والتأكيد مع GDT لذا يبدو NextDivel الآن كما يلي:

التاليDivel-GDT


اترك تعليقك

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها ب *

*

*

  1. المسؤول عن البيانات: ميغيل أنخيل جاتون
  2. الغرض من البيانات: التحكم في الرسائل الاقتحامية ، وإدارة التعليقات.
  3. الشرعية: موافقتك
  4. توصيل البيانات: لن يتم إرسال البيانات إلى أطراف ثالثة إلا بموجب التزام قانوني.
  5. تخزين البيانات: قاعدة البيانات التي تستضيفها شركة Occentus Networks (الاتحاد الأوروبي)
  6. الحقوق: يمكنك في أي وقت تقييد معلوماتك واستعادتها وحذفها.

  1.   سائرون قال

    ربما تكون بنية 64 بت أكثر ملاءمة لهذه الأوقات ، فهي عبارة عن تراكم لمواصلة استخدام 8086.

    1.    شارع أدريان أرويو قال

      لقد كنت أبحث عن معلومات حول GDT في x86_64 وأعتقد أنها تتبع النموذج القديم بعلم خاص. لا يزال يتم استخدام عنوان 32 بت. الآن لا أعرف بالضبط كيف أفعل ذلك بشكل صحيح. بعض الروابط:
      http://wiki.osdev.org/Entering_Long_Mode_Directly
      http://f.osdev.org/viewtopic.php?f=1&t=16275

  2.   جيرونيمو قال

    كانت أولى مساهماتك جيدة جدًا ، لكن أعتقد أن العنوان يجب أن يكون
    "محاكاة ريتشارد ستالمان" أو على الأقل أعتقد ذلك ،،،
    تحياتي

    1.    أبيالمارتيل قال

      أنشأ لينوس نواة لينكس ، وأنشأ ستالمان جنو وهي أدوات وأوامر يونكس.

      العنوان مناسب لأنك تقوم بإنشاء نواة.

      تحياتي!

  3.   روبي قال

    شكرًا جزيلاً لك على الإجابة على جميع أسئلتي والتحلي بالصبر ، فأنا أعرف فقط الأساسيات كمُجمِّع ولا أعرف شيئًا تقريبًا عن C ، لكنني أحب ذلك حقًا ، والآن أنا مرتبك قليلاً مع GDT ، دعنا نرى ما إذا كنت تفهم.

    ستحتوي GDT على "الواصفات" العالمية التي يمكن الوصول إليها دائمًا بواسطة أي برنامج ، وتشير هذه الواصفات إلى الأقسام التي سيتم تنفيذ (البرنامج) فيها؟ أو خلاف ذلك.