לדלג לתוכן

שימוש בinterrupts באסמבלי 8086

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


מהי interrupt?

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

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


פקודת INT

הפקודה:

INT number

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

INT 21h   ; call to DOS interrupt
INT 10h   ; call to BIOS display interrupt (screen)

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


הinterrupts חשובות ב־8086

DOS Interrupt – INT 21h

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

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

BIOS Interrupt – INT 10h

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

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

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

mov ah, 02h
mov dl, 'A'
int 21h         ; will print A to the screen

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

mov dx, offset msg
mov ah, 09h
int 21h         ; prints a string that ends with '$'

...

msg db 'Hello World!$', 0

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


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

mov ah, 01h
int 21h         ; waits for a keypress
; the character read will be in AL

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

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

...

buffer db 20         ; length limit (up to 19 characters)
       db 0          ; number of characters actually entered (filled in by DOS)
       db 20 dup(0)  ; space for the string

לאחר הקריאה:

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

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


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

mov ah, 0Eh
mov al, 'A'
mov bh, 0         ; page 0
mov bl, 7         ; color (foreground)
int 10h           ; will print A to the screen with scrolling

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


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

mov ah, 4Ch
int 21h

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

מה זה BIOS?

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

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

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

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

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

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

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

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

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

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

  • ועוד


איך פועלות interrupts?

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

int 10h

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

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

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

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


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

בזיכרון שמתחיל מהכתובת 0000:0000 (כתובת לינארית 0x00000)
יש טבלה בגודל 1024 בתים (0x400)
שבה יש 256 רשומות של interrupts, כל אחת בגודל 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.


האם אפשר לשנות interrupts?

כן – ניתן לשנות interrupts בצורה חוקית ומבוקרת ע"י טעינת כתובת אחרת ל־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        ; return from interrupt

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


שימושים נפוצים לשינוי interrupts

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

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

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

הinterrupts לא מתכוננות

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