יישום

המערך sys_imp כולל את כל המידע הנדרש לפסיקות XINU.

לכל פסיקה מוקצאת רשומה הכוללת את המידע הבא:

  • פקודת המכונה call intcom.
  • כתובת קוד ה-BIOS שהוצבע במקור מווקטור הפסיקות.
  • כתובת פונקצית הפסיקה של XINU.
  • מספר הפסיקה בווקטור הפסיקות.
  • זיהוי פנימי של ההתקן.
  • דגל המסמן האם לקרוא לקוד ה-BIOS לפני הקריאה לקוד ה-XINU.
  • גודל כל רשומה מסוג intmap הינו 14 בתים.

מבנה רשומה:

struct intmap {             /* device-to-interrupt routine mapping   */

       char   ivec;         /* interrupt number               */

       char   callinst;     /* the call instruction                  */

       word   intcom;       /* common interrupt code          */

       word   oldisr_off;   /* old int. service routine offset */

       word   oldisr_seg;   /* old int. service routine segment      */

       int    (*newisr)();  /* pointer to the new int. ser. routine */

       word   mdevno;       /* minor device number                   */

       word   iflag;        /* if nonzero, call the old isr          */

};

קבועים והגדרות הקשורים לטבלה זו:

extern struct intmap far *sys_imp; /* pointer to intmap table */

extern int    nmaps;               /* number of active intmap entries*/

#define       isbaddev(f)   ( (f)<0 || (f)>=NDEVS )

/* In-line I/O procedures */

#define       getchar()     getc(CONSOLE)

#define       putchar(ch)   putc(CONSOLE,(ch))

#define       fgetc(unit)   getc((unit))

#define       fputc(unit,ch)       putc((unit),(ch))

extern int    _doprnt();           /* output formatter               */

  • ווקטור הפסיקות מצביע על פקודת call intcom שברשומה המתאימה במערך sys_imp. לכן בעת פסיקה תקרא intcom כפונקציה מתוך הפסיקה.
  • intcom היא פונקציה כללית המשרתת את כל הפסיקות. אנו יודעים לאיזו פסיקה לקרוא לפי המיקום של intcom. הבית שאחרי פקודה זו נמצא על המחסנית ככתובת החזרה, בכתובת ss:bp+2.
  • על ידי ביצוע mov bx, [bp+2], אנו מקבלים ב-bx את "כתובת החזרה" המצביעה לתוך רשומת הפסיקה. כתובת שגרת הפסיקה המקורית נמצאת ב-plot:$\left( {cs:\left[ {bx + 2} \right]}
      \right):\left( {cs:\left[ {bx} \right]} \right)$.
  • כתובת שגרת הפסיקה של XINU היא cs:[bx+4]. כתובת mdevno היא cs:[bx+6].
  • כתובת iflag המציין האם לקרוא לשגרה המקורית היא cs:[bx+8].
  • בסוף פעולתה, intcom מוציאה את כתובת החזרה מהמחסנית, ומשתמשת ב-iret כדי לחזור לנקודה בה הייתה לפני הקפיצה לטבלה.
  • טבלת הפסיקות נמצאת בסגמנט התוכנית, cs, שהינו לא נגיש עבור תוכניות C רגילות. מכיוון שאנו רוצים לאתחל את המערך מתוך C, מוגדר המשתנה sys_imp המכיל מצביע (סגמנט + offset) אל הטבלה.

intcom()

  • קוראת לקוד הפסיקה הישן במידה ש-iflag דולק.
  • מכבה את דגל הפסיקות, כדי לוודא שקוד הפסיקה הישן לא הדליק אותו.
  • שומרת את ערכי כל הרגיסטרים.
  • אם הפסיקה ארעה כאשר התבצע קוד של XINU:
  • אם הפסיקה ארעה מתוך קוד שאינו של XINU

    (למשל בזמן ביצוע פסיקתBIOS - ROM כאשר דגל הפסיקות דולק):
  • נמנעת החלפת תהליכים ע”י איפוס pcxflag.
  • נקרא קוד הפסיקה של XINU.
  • משוחזרים pcxflag והמחסנית הישנה.
  • משוחזרים כל הרגיסטרים.
  • כתובת החזרה מ- intcom מוצאת מהמחסנית ומתבצע iret.

הערה: ב-intcom, קביעת ה-pcxflag ל-0 נעשית אחרי החלפת המחסנית ולא לפני, אולם זו איננה בעיה מכיוון שהפסיקות מכובות בקטע זה, ולכן לא תתכן החלפת תהליכים.

מבנה המחסנית בזמן הקריאה ל-intcom

Stack Offset

Stack Contents

0

es

1

ds

2

di

3

si

4

dx

5

cx

6

bx

7

ax

8

bp

9

ret address to intmap table, offset 4

10

IRET offset address

11

IRET segment address

12

IRET flags

13

user code

  • intcom מתחילה את פעולתה בדחיפת bp, ax, bx אל המחסנית.

תגיות המסמך:

מאת: באסל

תודה

הסברתם את זה, כמו שאר הנושאים, באופן הכי ברור שיש.
שיתוף:
| עוד