端口的讀寫
對端口的讀寫不能用mov、push、pop等內存讀寫指令。
端口的讀寫指令只有兩條:in和out,分別用於從端口讀取數據和往端口寫入數據。
訪問內存:mov ax,ds:[8];假設執行前(ds)=0
執行時,與總線相關的操作:
① CPU通過地址線將地址信息8發出;
② CPU通過控制線發出內存讀命令,選中存儲器芯片,並通知它,將要從中讀取數據;
③ 存儲器將 8號單元中的數據通過數據線送入CPU。
訪問端口:in al,60h;從60h號端口讀入一個字節
執行時與總線相關的操作:
① CPU通過地址線將地址信息60h發出;
② CPU通過控制線發出端口讀命令,選中端口所在的芯片,並通知它,將要從中讀取數據;
③ 端口所在的芯片將60h端口中的數據通過數據線送入CPU。
注意:在in和out 指令中,只能使用 ax 或al 來存放從端口中讀入的數據或要發送到端口中的數據。訪問8 位端口時用 al ,訪問16 位端口時用ax 。
對0~255以內的端口進行讀寫:
- in al,20h ;從20h端口讀入一個字節
- out 20h,al ;往20h端口寫入一個字節
對256~65535的端口進行讀寫時,端口號放在dx中:
- mov dx,3f8h ;將端口號3f8送入dx
- in al,dx ;從3f8h端口讀入一個字節
- out dx,al ;向3f8h端口寫入一個字節
shl和shr指令
shl邏輯左移指令,功能為:
(1)將一個寄存器或內存單元中的數據(二進制類型)向左移位;
(2)將最后移出的一位寫入CF中;
(3)最低位用0補充。
指令:mov al,01001000b
shl al,1 ;將al中的數據左移一位
執行后(al)=10010000b,CF=0。
如果移動位數大於1時,必須將移動位數放在cl中。
比如,指令:
mov al,01010001b
mov cl,3
shl al,cl
執行后(al)=10001000b,因為最后移出一位是0,所以CF=0。
將X邏輯左移一位,相當於執行X=X*2。
shr邏輯右移指令
它和shl所進行的操作剛好相反:
(1)將一個寄存器或內存單元中的數據向右移位;
(2)將最后移出的一位寫入CF中;
(3)最高位用0補充。
編程:在屏幕中間顯示當前的月份。
分析:這個程序主要做兩部分工作:
(1)從CMOS RAM的8號單元讀出當前月份的BCD碼;要讀取 CMOS RAM的信息,我們首先要向地址端口70h寫入要訪問的單元的地址:
mov al,8
out 70h,al
然后從數據端口71h中取得指定單元中的數據:in al,71h
(2)將用BCD碼表示的月份以十進制的形式顯示到屏幕上。
我們可以看出 ,BCD 碼值=十進制數碼值,則BCD碼值+30h=十進制數對應的ASCII碼。
從CMOS RAM的8號單元讀出的一個字節中,包含了用兩個 BCD 碼表示的兩位十進制數,高4位的 BCD碼表示十位,低 4位的 BCD碼表示個位。比如:00010100b表示14。
1 assume cs:code 2 code segment 3 start:mov al,8 4 out 70h,al ; 從地址端口70h,寫入要訪問的內存單元的地址 5 in al,71h ; 從數據端口71h,獲取第8號內存單元(月)的數據 6 mov ah,al ; 將月的值賦給ah 7 8 mov cl,4 ; 右移4次 9 shr ah,cl ; 獲取月份十位數的值(因為要把每一位數+30h) 10 and al,0000 1111b ; 獲取月份十位數的值 11 12 add ah,30h 13 add al,30h ; BCD碼 ==> ASCII碼 14 15 mov bx,0b800H ; 定位到顯存的位置 16 mov ds,bx ; 我也不知道要寫啥 17 mov byte ptr ds:[160*12+40*2],ah 18 mov byte ptr ds:[160*12+40*2+2],al 19 20 mov ax,4c00h 21 int 21h 22 code ends 23 end start