לדלג לתוכן

שימוש בפסיקות (Interrupts) באסמבלי 8086

כאשר אנחנו כותבים קוד אסמבלי למעבד 8086, לעיתים קרובות נרצה לבצע פעולות מתקדמות: הדפסת טקסט למסך, קריאה מהמקלדת, גישה לקבצים ולכוננים, שינוי צבעים במסך, ועוד.
בהרצאה הבאה נציג כיצד אנחנו יכולים לכתוב קוד אסמבלי שיודע לדבר עם התקני הקלט והפלט כדי לבצע את הפעולות הללו בעצמכם.
בדרך כלל לא נהוג לכתוב קוד שיודע לבצע את הפעולות בעצמנו, במקום שנצטרך לממש את כל הדברים האלו בעצמנו – אנחנו יכולים לקרוא לשירותים שהמערכת מספקת, דרך מנגנון שנקרא פסיקות – Interrupts.


מהי פסיקה (Interrupt)?

פסיקה היא מנגנון שבו אנחנו מפסיקים את זרימת התוכנית, וקופצים לבצע קוד מיוחד שמוגדר מראש. (בדרך כלל מטרתו היא לדבר עם המקלדת, המסך וכו)
ישנן המון סוגים של פסיקות שאנחנו יכולים לקרוא להן, ובדרך כלל יש שני מערכות שאחראיות להוסיף פסיקות.
1. מערכת הBIOS- מערכת הBIOS היא קוד שרץ לפני שכל קוד במערכת רץ, חלק מהאחריות של הBIOS היא להגדיר פסיקות בסיסיות שימושיות- כמו הדפסת פיקסלים על המסך, קריאה של מידע מהמקלדת וכו.
2. לאחר שהBIOS סיים לרוץ, לרוב זה השלב שבו תרוץ מערכת ההפעלה. בדרך כלל גם מערכת ההפעלה מוסיפה פסיקות שונות לשימוש תוכנות שרצות במערכת ההפעלה

למעשה נוצר מצב שכשאנחנו כותבים תוכנות שרצות בms-dos קיימות לנו המון פסיקות שימושיות שהוגדרו על ידי הBIOS ומערכת ההפעלה שבאמצעותן נוכל לכתוב תוכנות שימושיות בקלות יותר.


פקודת INT

הפקודה:

INT מספר

תגרום למעבד לקפוץ ולבצע את הפונקציה המתאימה למספר הפסיקה. לדוגמה:

INT 21h   ; קריאה לפסיקת DOS
INT 10h   ; קריאה לפסיקת BIOS של תצוגה (מסך)

איך יודעים מה הפעולה שיבצעו?
דרך ערכים שאנחנו שמים ברגיסטר AH, ולפעמים גם ב־AL, BX, DX וכו'.


פסיקות חשובות ב־8086

פסיקת DOS – INT 21h

משמשת לביצוע שירותי מערכת תחת MS-DOS: הדפסת טקסט, קריאת קלט, פתיחת קבצים, גישה לדיסק וכו'.

AH פעולה
01h קריאת תו מהמקלדת
02h הדפסת תו (ב־DL)
09h הדפסת מחרוזת שמסתיימת ב־$
0Ah קריאת מחרוזת מהמקלדת
4Ch יציאה מהתוכנית

פסיקת BIOS – INT 10h

משמשת לפעולות הקשורות למסך ותצוגה: הדפסת תווים, שינוי מצב וידאו, שינוי צבעים ועוד.
בהמשך נדבר יותר על איך לעשות גרפיקה עם פסיקות של הBIOS

דוגמאות קוד: הדפסה וקלט

הדפסת תו בודד (INT 21h, AH=02h)

mov ah, 02h
mov dl, 'A'
int 21h         ; ידפיס A למסך

הדפסת מחרוזת (INT 21h, AH=09h)

mov dx, offset msg
mov ah, 09h
int 21h         ; מדפיס מחרוזת שמסתיימת ב־'$'

...

msg db 'Hello World!$', 0

שימו לב: המחרוזת חייבת להסתיים בסימן $ כדי שהפסיקה תדע מתי להפסיק להדפיס!


קריאת תו מהמקלדת (INT 21h, AH=01h)

mov ah, 01h
int 21h         ; ממתין ללחיצה
; התו הנקלט יהיה ב־AL

קריאת מחרוזת מהמקלדת (INT 21h, AH=0Ah)

mov ah, 0Ah
mov dx, offset buffer
int 21h

...

buffer db 20         ; הגבלת אורך (עד 19 תווים)
       db 0          ; מספר התווים שהוזנו בפועל (יוכנס ע"י DOS)
       db 20 dup(0)  ; מקום למחרוזת

לאחר הקריאה:

  • buffer+1 יכיל את אורך המחרוזת

  • buffer+2 והלאה יכילו את התווים שהוקלדו


הדפסת תווים עם פסיקת BIOS (INT 10h, AH=0Eh)

mov ah, 0Eh
mov al, 'A'
mov bh, 0         ; עמוד (page) 0
mov bl, 7         ; צבע (foreground)
int 10h           ; ידפיס A למסך עם גלילה

הפסיקה הזו כותבת למסך תווים גולמיים, ומתקדמת שורה אוטומטית.


יציאה מהתוכנית (INT 21h, AH=4Ch)

mov ah, 4Ch
int 21h

זהו הסיום התקני של תוכנית DOS. ללא זה, התוכנית עלולה "לרוץ" אל זיכרון לא תקף ולקרוס.

מה זה BIOS?

הBIOS = Basic Input Output System
זהו קוד שנמצא בתוך שבב ROM על לוח האם של המחשב, ופועל מיד עם הדלקת המחשב.

המטרה של ה-BIOS היא לספק קוד בסיסי ביותר להפעלת רכיבי המחשב, כולל:

  • טעינת מערכת ההפעלה

  • קריאה וכתיבה לזיכרון

  • גישה למסך, מקלדת, דיסק, יציאות וכו'

ה-BIOS מספק שירותים חשובים בתור פסיקות, כמו:

  • הדפסת תו למסך (INT 10h)

  • קריאה מהמקלדת (INT 16h)

  • גישה לדיסק (INT 13h)

  • מדידת זמן (INT 1Ah)

  • ועוד


איך פועלות פסיקות?

כאשר אנחנו כותבים למשל:

int 10h

המעבד מבצע את הצעדים הבאים:

  1. מחשב את הכתובת בזיכרון שבה מאוחסן ה־Vector של הפסיקה (עוד רגע נסביר מה זה).

  2. קורא מ־Vector זה את כתובת הקוד (Segment:Offset) שממומשת ע"י BIOS.

  3. קופץ לביצוע הקוד הזה – כאילו זו קריאה לפונקציה.


טבלת וקטורי הפסיקה – Interrupt Vector Table

בזיכרון שמתחיל מהכתובת 0000:0000 (כתובת לינארית 0x00000)
יש טבלה בגודל 1024 בתים (0x400)
שבה יש 256 רשומות של פסיקות, כל אחת בגודל 4 בתים:

  • 2 בתים – offset

  • 2 בתים – segment

כלומר:

  • INT 00h → וקטור נמצא בכתובת 0000:0000

  • INT 01h0000:0004

  • INT 10h0000:0040

  • INT 21h0000:0084

וכך הלאה.

לדוגמה, עבור INT 10h, המעבד יקרא את 4 הבתים החל מהכתובת 0x0040:

  • נניח שהערכים הם: 00 F0 00 C0

  • אז ה־offset = F000h, segment = C000h

  • כלומר, כתובת הביצוע היא C000:F000


איפה נמצא ה־BIOS בזיכרון?

לרוב, ה־BIOS ממופה לזיכרון הגבוה ביותר של המערכת –
החל מהכתובת F000:0000 (כתובת פיזית 0xF0000), בגודל 64KB.

שם נמצא הקוד עצמו שה־interrupt vectors מפנים אליו.


דוגמה – איך INT 10h באמת עובד?

int 10h

המעבד קורא את ה־vector מהכתובת 0000:0040, למשל:

[C000:F000]

כלומר – הקוד שאחראי להדפסת תווים במסך נמצא בתוך ה־ROM של ה־BIOS.


האם אפשר לשנות פסיקות?

כן – ניתן לשנות פסיקות בצורה חוקית ומבוקרת ע"י טעינת כתובת אחרת ל־IVT.
כלומר – אנחנו יכולים לשים קוד משלנו בזיכרון, ואז לשנות את ה־vector שיפנה לקוד שלנו.

דוגמה – החלפת INT 60h לקוד משלך

mov ax, seg myhandler
mov ds, ax
mov word ptr [0x0060*4], offset myhandler     ; offset
mov word ptr [0x0060*4+2], ax                 ; segment

כעת כל קריאה ל־INT 60h תקפוץ ל־myhandler שלך.


דוגמה לפונקציה משלך

myhandler:
    push ax
    mov ah, 0Eh
    mov al, '*'
    int 10h
    pop ax
    iret        ; חזרה מפסיקה

פקודת IRET חשובה מאוד – היא לא RET רגיל, אלא מחזירה גם את ערכי ה־flags.


שימושים נפוצים לשינוי פסיקות

  • קריאה לפסיקה מותאמת אישית: כמו INT 60h-6Fh (לא בשימוש ע"י BIOS)

  • ביצוע "Hook" לפסיקות קיימות: לדוגמה, פסיקות מקלדת, טיימר, או הדפסה, כדי להוסיף קוד משלך או שינוי של הפסיקות הקיימות.

  • בכתיבת מערכת הפעלה, נהוג ליצור פסיקות- כמו בms-dos שיש לנו המון קריאות מערכת שאנחנו יכולים לעשות עם int 21.

פסיקות לא מתכוננות

פסיקה היא פעולה שעוצרת את כל מה שהמעבד עושה, "מפסיקה" את מה שהמעבד עושה, כדי לבצע פעולה מגודרת מראש בטבלת הivt.
עד כו למדנו על פסיקות שאנחנו קוראים להם בעצמנו עם הפקודה int.
אבל פסיקות יכולות לקרות גם אם לא קראנו להם בכלל, פסיקות יכולות לקרות גם אם
המשתמש לחץ על מקש.
הגיע מידע מהכונן הקשיח. (הhard disk, האחסון)
בעתיד נלמד על פסיקות שעלולות לקרות למעבד, בנתיים- זכרו שיש המון סוגי פסיקות- ופסיקות יכולות לקרות גם אם לא תכננו.