חיקוי לינוס טורבלדס: צור מערכת הפעלה משלך מאפס (III)

אנו ממשיכים בסדרת הפוסטים הזו כיצד ליצור את מערכת ההפעלה שלנו. היום אנחנו לא מתכוונים להתמקד בנושא אחד אבל אנחנו הולכים להגדיר כמה פונקציות שימושיות מעתה ואילך. ראשית אנו הולכים להגדיר 3 פונקציות הממלאות את הפונקציה של memcpy, ממט y 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 קטנה, היישום בדרך כלל דומה בכל מערכות ההפעלה. עכשיו אנחנו הולכים לעשות 3 פונקציות מדומות אבל לתפעל מחרוזות. הם היו ממלאים את הפונקציה של strcpy, strcat y strcmp.

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 סיביות שאני עובד על תיקון a באג מה שמונע קומפילציה נכונה ב 64 ביט. בפוסט הבא נראה מרכיב חשוב בארכיטקטורת x86, ה- GDT.


השאירו את התגובה שלכם

כתובת הדוא"ל שלך לא תפורסם. שדות חובה מסומנים *

*

*

  1. אחראי לנתונים: מיגל אנחל גטון
  2. מטרת הנתונים: בקרת ספאם, ניהול תגובות.
  3. לגיטימציה: הסכמתך
  4. מסירת הנתונים: הנתונים לא יועברו לצדדים שלישיים אלא בהתחייבות חוקית.
  5. אחסון נתונים: מסד נתונים המתארח על ידי Occentus Networks (EU)
  6. זכויות: בכל עת תוכל להגביל, לשחזר ולמחוק את המידע שלך.

  1.   שם דיג'ו

    בואו נראה אם ​​אתם מגיבים כיצד לפתור את הבאג, כי לא התקדמתי מהחלק הראשון.

    1.    O_Pixote_O דיג'ו

      אני חושב שהם הגיבו על השגיאה בתגובות פוסט 2. הם חשבו שזה משהו מהגרוב אם אני זוכר נכון

  2.   כחול גולגולת דיג'ו

    להעתיק ביי להתראות?

    1.    כחול גולגולת דיג'ו

      ככל הנראה בתים אחר בתים ..., 2 כישלונות רצופים אינם מצליחים, אושר.

  3.   ruby232 דיג'ו

    תודה רבה על ההודעה הטובה מאוד ואני עוקב אחריה, יש לי כמה שאלות:
    1. כשאתה אומר 'להתקשר בקלות ל- ASM מ- C משתמשים בהוראות asm, עם הסכנה שזה טומן בחובו שהוא לא נייד', למה אתה מתכוון כשאומרים 'עם הסכנה שזה טומן בחובו שהוא לא נייד ?

    2. אם הייתה מתבצעת מערכת הפעלה 'מקצועית' (כביכול) חלק זה של הגישה לחומרה ייעשה ב- Assembler.

    3. איך זה היה מתבצע אצל אסמבלר?

    1.    אדריאן ארויו סטריט דיג'ו

      תודה לך על כך שאתה עונה על השאלות אחת אחת:
      1- ובכן, הבעיה בהוראות asm היא שהיא לא קיימת בשום תקן C, ולכן כל מהדר מיישם אותה בדרכה שלה (אם הוא מיישם אותה). במקרה זה ניתן להרכיב אותו עם GCC ו- Clang (זה נראה הרבה כמו GCC מהבחינה הזו) אך לא תוכלו לעשות במהדרים אחרים כמו אינטל C (זה משתמש באינטל תחביר ב- ASM).
      2- מבחינה מקצועית, יש להפריד בין חלק אחד לשני על ידי ארכיטקטורות וחלק משותף אחר. אין צורך לעשות זאת במאסף (לינוקס יש את זה בתוך C)
      3- גם במאסף זה פשוט מאוד, אבל יש לך את זה בקובץ נפרד. מצד שני, לאחר שיש טיעונים עלינו להעביר אותו תחילה לרשומות וזה יכול לפשל עוד קצת, ואז יופעל ה- outb או ה- inb והפונקציה הוכרזה כגלויה ברחבי העולם. ואז מ- C עליך להכין כותרת המכריזה על פונקציה "חיצונית". ב- NASM (תחביר אינטל) זה יהיה בערך כך:
      outb:
      לדחוף ebp
      mov ebp, esp

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

      החוצה dx אל

      mov esp, ebp
      פופ ebp
      ret

  4.   מקס דיג'ו

    שאלה, באיזה תחביר אתה משתמש? אני לא מבין מדוע כל כך הרבה ASM xD MASM, FASM, NASM, AT & T שונים כל כך ...
    ואם יש לך זמן, תוכל להסביר את השורה:
    asm נדיף ("outb% 1,% 0" :: "dN" (port), "a" (value));

    עד ש- "asm volatile" הבנתי את xD "outbyte 1,0?"
    או שזה 1 -> »dN» (יציאה), 0 -> «a» (ערך)?
    אם זה האחרון, אני לא מבין מה זה "dn" ומה זה "a" ...

    תודה רבה על תרומתך! מדהים !!

    1.    אדריאן ארויו סטריט דיג'ו

      התחביר בו אני משתמש הוא AT&T ובזה GCC משתמש באופן פנימי אם כי ניתן לעשות זאת ללא בעיות ב- NASM (התאמת התחביר). לגבי אותה הצהרה מורכבת של תנודתיות asm, אני יכול רק לומר לך שזה המקרה בגלל ה- GCC שכן הוא משתמש בכמה פרמטרים כדי לדעת כיצד יש להעביר את הנתונים. לדוגמא "a" הוא אופרנד x86 מיוחד המשמש לייצוג ה- register. הרשימה כולה נמצאת כאן: http://gcc.gnu.org/onlinedocs/gcc/Constraints.html#Constraints

  5.   52 דיג'ו

    בסדר, אני באמת זקוק לעזרה, אני חדש בזה ואין לי שמץ של מושג מה לעשות עם מה שכתוב בטרמינל, מישהו יכול לעזור לי?