לדלג לתוכן

1.7 קלט ופלט פתרון

תרגיל 1 - read_key.asm

IDEAL
MODEL small
STACK 100h

CODESEG
start:
    mov dx, 0x60       ; כתובת פורט המקלדת
    in al, dx          ; קרא תו מהפורט

    mov ah, 0Eh        ; שירות תצוגה של BIOS
    mov bh, 0
    mov bl, 7
    int 10h            ; הצג את התו

    mov ax, 4C00h      ; סיום תקני
    int 21h
END start

תרגיל 2 - wait_and_read.asm

IDEAL
MODEL small
STACK 100h

CODESEG
start:
wait_key:
    in al, 0x64        ; בדוק את פורט הסטטוס של המקלדת
    test al, 1         ; האם ביט 0 דולק? (תו מוכן?)
    jz wait_key        ; אם לא - המשך לחכות

    in al, 0x60        ; קרא את התו מפורט המקלדת

    mov ah, 0Eh        ; שירות TTY של BIOS
    mov bh, 0
    mov bl, 7
    int 10h            ; הצג את התו

    mov ax, 4C00h
    int 21h
END start

הסבר: הפקודה TEST AL, 1 מבצעת AND לוגי בין AL לבין 1 (ביט 0 בלבד). אם התוצאה היא 0 - סימן שאין תו מוכן, ו-JZ מחזיר אותנו ללולאה. כשביט 0 דולק - יש תו מוכן ואפשר לקרוא אותו מפורט 0x60.


תרגיל 3 - write_port.asm

IDEAL
MODEL small
STACK 100h

CODESEG
start:
    mov dx, 0x300           ; כתובת הפורט של כרטיס הנוריות

    mov al, 0b11001100      ; ערך ראשון - מדליק חלק מהנוריות
    out dx, al              ; שלח לפורט

    mov al, 0b00110011      ; ערך שני - מדליק נוריות אחרות
    out dx, al              ; שלח לפורט

    mov ax, 4C00h           ; סיום תקני
    int 21h
END start

הסבר: בכל פקודת OUT, הערך שב-AL עובר דרך ה-Data Bus, וכתובת הפורט שב-DX עוברת דרך ה-Address Bus. ההתקן בפורט 0x300 מקבל את הערך ומדליק את הנוריות בהתאם לביטים הדולקים.


תרגיל 4 - keyboard_driver.asm

IDEAL
MODEL small
STACK 100h

CODESEG
start:
keyboard_loop:
    in al, 0x64         ; בדוק את סטטוס המקלדת
    test al, 1          ; האם ביט 0 דולק? (יש תו מוכן?)
    jz keyboard_loop    ; אם לא - חזור לתחילת הלולאה

    in al, 0x60         ; קרא את התו מפורט המקלדת

    mov ah, 0Eh         ; שירות TTY של BIOS
    mov bh, 0
    mov bl, 7
    int 10h             ; הצג את התו על המסך

    jmp keyboard_loop   ; חזור ללולאה - המשך לקרוא תווים
END start

הסבר: זהו דרייבר מקלדת פשוט שרץ בלולאה אינסופית. בכל סיבוב הוא בודק אם יש תו מוכן, ואם כן - קורא אותו ומציג אותו. שימו לב שהתוכנית לא מסתיימת - היא רצה לנצח כמו שדרייבר אמיתי היה עושה. בעולם האמיתי, דרייבר מקלדת עובד עם פסיקות ולא עם לולאת polling כזו, אבל העיקרון דומה.


תרגיל 5 - תשובות לשאלות ההבנה

1. מה עובר בכל Bus בפקודת OUT DX, AL?

  • Data Bus - הערך שנמצא ב-AL (הנתון שנשלח להתקן)
  • Address Bus - כתובת הפורט שנמצאת ב-DX
  • Control Bus - אות IO Write (לא Memory Write) - שמציין שמדובר בכתיבה לפורט I/O ולא לזיכרון RAM

2. מה ההבדל בין Memory-Mapped I/O לבין Port-Mapped I/O?

  • ב-Memory-Mapped I/O - התקני ה-I/O מקבלים כתובות בתוך מרחב הכתובות של ה-RAM. פונים אליהם עם אותן פקודות שפונים לזיכרון (MOV וכו').
  • ב-Port-Mapped I/O (שבו אנחנו משתמשים ב-8086) - יש מרחב כתובות נפרד ייעודי ל-I/O. פונים אליו רק עם הפקודות IN ו-OUT. ה-Control Bus מבדיל בין גישה לזיכרון לבין גישה ל-I/O.

3. כמה פורטים יכולים להיות ב-8086?

תאורטית - 64KB של פורטים (כתובות 0x0000 עד 0xFFFF, כי כתובת הפורט היא 16 ביט). בפועל, לרוב משתמשים ב-256 פורטים בלבד (כתובות 0x00 עד 0xFF).

4. למה DX משמש תמיד לכתובת הפורט?

זוהי מוסכמה קבועה של ארכיטקטורת x86. הפקודות IN ו-OUT תוכננו כך שהן תמיד משתמשות ב-DX לכתובת הפורט וב-AL/AX לנתון. זה חלק מהגדרת ה-ISA (Instruction Set Architecture) של המעבד - לא ניתן לשנות את זה או להשתמש ברגיסטר אחר.