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

نواصل هذه السلسلة من المنشورات حول كيفية إنشاء نظام التشغيل الخاص بنا. اليوم لن نركز على موضوع واحد ولكننا سنحدد بعض الوظائف المفيدة من الآن فصاعدًا. أولاً ، سنقوم بتحديد 3 وظائف تفي بوظيفة com.memcpy, memeset y com.memcmp:

void* ND::Memory::Set(void* buf, int c, size_t len)
{
unsigned char* tmp=(unsigned char*)buf;
while(len--)
{
*tmp++=c;
}
return buf;
}
void* ND::Memory::Copy(void* dest,const void* src, size_t len)
{
const unsigned char* sp=(const unsigned char*)src;
unsigned char* dp=(unsigned char*)dest;
for(;len!=0;len--) *dp++=*sp++;
return dest;
}
int ND::Memory::Compare(const void* p1, const void* p2, size_t len)
{
const char* a=(const char*)p1;
const char* b=(const char*)p2;
size_t i=0;
for(;i<len;i++)
{
if(a[i] < b[i]) return -1; else if(a[i] > b[i])
return 1;
}
return 0;
}

كل منهم ذاتي التنفيذ. هذه الوظائف التي أخذتها من مكتبة C صغيرة ، وعادة ما يكون التنفيذ مشابهًا في جميع أنظمة التشغيل. الآن نحن بصدد القيام بثلاث وظائف محاكاة ولكن للتعامل مع السلاسل. سوف يقومون بوظيفة سترسبي, سترات y ستركمب.

size_t ND::String::Length(const char* src)
{
size_t i=0;
while(*src--)
i++;
return i;
}
int ND::String::Copy(char* dest, const char* src)
{
int n = 0;
while (*src)
{
*dest++ = *src++;
n++;
}
*dest = '';
return n;
}
int ND::String::Compare(const char *p1, const char *p2)
{
int i = 0;
int failed = 0;
while(p1[i] != '' && p2[i] != '')
{
if(p1[i] != p2[i])
{
failed = 1;
break;
}
i++;
}
if( (p1[i] == '' && p2[i] != '') || (p1[i] != '' && p2[i] == '') )
failed = 1;
return failed;
}
char *ND::String::Concatenate(char *dest, const char *src)
{
int di = ND::String::Length(dest);
int si = 0;
while (src[si])
dest[di++] = src[si++];
dest[di] = '';
return dest;
}

نحن نذهب الآن مع بعض الوظائف المثيرة للاهتمام. مع هذه الوظائف يمكننا القراءة والكتابة على منافذ الأجهزة. يتم ذلك عادةً باستخدام ASM ويتوافق (في x86) مع التعليمات in y خارج. للاتصال بسهولة ASM من C ، استخدم التعليمات ASM، مع ما يترتب على ذلك من خطورة أنها غير محمولة. إلى هذه الجملة نضيف متقلب بحيث لا يحاول GCC تحسين هذا النص. من ناحية أخرى ، فإن تعليمة ASM لديها طريقة غريبة لقبول المعلمات ، لكنني أعتقد أن هذا يمكن فهمه بشكل أفضل من خلال النظر إلى الأمثلة.

void ND::Ports::OutputB(uint16_t port, uint8_t value)
{
asm volatile("outb %1, %0" : : "dN"(port), "a"(value));
}
uint8_t ND::Ports::InputB(uint16_t _port)
{
unsigned char rv;
asm volatile("inb %1, %0" : "=a"(rv) : "dN"(_port));
return rv;
}

وحتى الآن بعد 3 ، لم نقم اليوم بأي شيء مبهرج ولكننا حددنا وظائف ستكون مفيدة للمستقبل. إشعار لمستخدمي 64 بت أنني أعمل على إصلاح ملف علة مما يمنع الترجمة بشكل صحيح في 64 بت. في المنشور التالي ، سنرى مكونًا مهمًا في بنية x86 ، GDT.


اترك تعليقك

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

*

*

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

  1.   اسم قال

    دعنا نرى ما إذا كنت تعلق على كيفية حل الخطأ ، لأنني لم أتقدم من الجزء الأول.

    1.    O_Pixote_O قال

      أعتقد أنهم علقوا على الخطأ في تعليقات المنشور 2. اعتقدوا أنه شيء من اليرقة إذا كنت أتذكر بشكل صحيح

  2.   جمجمة زرقاء قال

    نسخ وداعا؟

    1.    جمجمة زرقاء قال

      من الواضح أن بايت بايت ... ، 2 فشل متتالي لا ينجح ، أكد.

  3.   ruby232 قال

    شكرا جزيلا لك على المنشور الجيد جدا وأنا أتابعها ولدي بعض الأسئلة:
    1. عندما تقول "لاستدعاء ASM من C بطريقة سهلة ، يتم استخدام تعليمات ASM ، مع وجود خطر من أنها ليست محمولة" ، فماذا تقصد عندما تقول "مع الخطر الذي ينطوي عليه أنها ليست محمولة "؟

    2. إذا تم إنشاء نظام تشغيل "احترافي" (إذا جاز التعبير) ، فسيتم تنفيذ هذا الجزء من الوصول إلى الأجهزة في المجمع.

    3. كيف يتم عمل ذلك في المجمع؟

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

      شكرًا لك على متابعتك ، سأجيب على الأسئلة واحدًا تلو الآخر:
      1- حسنًا ، مشكلة تعليمة ASM هي أنها غير موجودة في أي معيار C ، لذلك يقوم كل مترجم بتنفيذها بطريقته الخاصة (إذا قام بتنفيذها). في هذه الحالة ، يمكن تجميعها باستخدام GCC و Clang (يبدو كثيرًا مثل GCC في هذا الصدد) ولكنك لن تتمكن من ذلك في المجمعين الآخرين مثل Intel C (يستخدم هذا Intel Syntax في ASM).
      2- مهنياً ، يجب فصل جزء وآخر بشكل واضح عن طريق معماريات وجزء مشترك آخر. ليس من الضروري القيام بذلك في المجمّع (يوجد في Linux داخل C)
      3- في المجمع ، يكون الأمر بسيطًا جدًا أيضًا ، لكن لديك في ملف منفصل. من ناحية أخرى ، عند وجود وسيطات ، يجب علينا أولاً تمريرها إلى السجلات ويمكن أن يفسد ذلك قليلاً ، ثم يتم استدعاء outb أو inb ويتم الإعلان عن الوظيفة على أنها مرئية عالميًا. ثم من C ، سيتعين عليك إنشاء رأس يعلن عن وظيفة "خارجية". في NASM (Intel Syntax) سيكون شيئًا مثل هذا:
      الخارج:
      دفع ebp
      mov ebp، esp

      mov eax، [ebp + 12]
      mov edx، [ebp + 8]

      خارج DX ، آل

      mov esp ، ebp
      البوب ​​ebp
      عطن

  4.   اكثر شئ قال

    سؤال ، ما هو النحو الذي تستخدمه؟ لا أفهم سبب وجود العديد من أجهزة ASM xD MASM و FASM و NASM و AT & T ...
    وإذا كان لديك وقت ، هل يمكن أن تشرح الخط:
    asm متغير ("outb٪ 1،٪ 0" :: "dN" (منفذ)، "a" (قيمة))؛

    حتى "ASM متقلب" هل فهمت xD "outbyte 1,0،XNUMX؟"
    أم أنه 1 -> »dN» (منفذ) ، 0 -> «a» (قيمة)؟
    إذا كان هذا هو الأخير ، فأنا لا أفهم ما هو "dn" وما هو "a" ...

    شكرا جزيلا لمساهماتك! لا يصدق !!

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

      الصيغة التي أستخدمها هي AT&T وهو ما تستخدمه دول مجلس التعاون الخليجي داخليًا على الرغم من أنه يمكن إجراؤها دون مشاكل في NASM (تكييف البنية). فيما يتعلق بهذا البيان المعقد لـ ASM المتقلب ، لا يمكنني إلا أن أخبرك أن هذا هو الحال بسبب دول مجلس التعاون الخليجي لأنه يستخدم بعض المعلمات لمعرفة كيفية تمرير البيانات. على سبيل المثال ، "a" هو معامل x86 خاص يستخدم لتمثيل السجل. القائمة الكاملة هنا: http://gcc.gnu.org/onlinedocs/gcc/Constraints.html#Constraints

  5.   52- ندى قال

    حسنًا ، أنا حقًا بحاجة إلى المساعدة ، أنا جديد على هذا وليس لدي أدنى فكرة عما أفعله بما هو مكتوب في الجهاز ، هل يمكن لأي شخص مساعدتي؟