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) של המעבד - לא ניתן לשנות את זה או להשתמש ברגיסטר אחר.