汇编学习--第十六天

第十四章 端口

CPU可以直接读写数据的地方:

  1. CPU内部的寄存器
  2. 内存单元
  3. 端口

14.1 端口的读写

对8位端口进行读写,用al保存数据,对16位端口进行读写,用ax保存数据

对0~255以内端口进行读写时

in al,20h
out 20h,al

 

对256~65535端口进行读写时,需要用dx保存端口号

mov dx,3f8h
in al,dx
out dx,al

 

14.2 CMOS RAM

70h地址端口:存放要访问的CMOS RAM单元的地址

71h数据端口:存放从选定的CMOS EAM单元中读取数据

 

(1)

assume cs:code
code segment
start:
    mov al,2
    out 70h,al
    in al,71h
    
    mov ax,4c00h
    int 21h
code ends
end start

 

(2)

assume cs:code
code segment
start:
    mov al,2
    out 70h,al
    mov al,0
    out 71h,al
    
    mov ax,4c00h
    int 21h
code ends
end start

 

14.3 shl和shr指令

shl逻辑左移指令

shr逻辑右移指令

 

功能:

  1. 将一个寄存器或内存单元中的数据左/右移位
  2. 将最后移出的一位写入CF中
  3. 最低位/最高位用0补存

 

如果要移动一位以上,需要用cl寄存器保存次数

 

检测点 14.2

assume cs:code
code segment
start:
    mov ax,66
    mov bx,ax
    shl ax,1
    mov cl,3
    shl bx,cl
    add ax,bx
    
    mov ax,4c00h
    int 21h
code ends
end start

 

14.4 CMOS RAM中储存的时间信息

存放的当前时间包括:年,月,日,时,分,秒,长度都为1字节,存放单元在

秒:0  分:2  时:4

日:7  月:8  年:9

 

实验14 访问CMOS RAM

assume cs:code
data segment
    db 9,8,7,4,2,0
data ends
code segment
start:
    mov ax,data
    mov ds,ax
    mov bx,0b800h
    mov es,bx
    mov di,160*12+33*2
    mov si,0
    mov cx,6
    
s:
    call show
    
    cmp byte ptr ds:[si],7
    jna s1;不大于7就跳转
    ;年,月
    mov byte ptr es:[di],'/'
    jmp stop
s1:
    jb s2;小于7就跳转
    ;
    mov byte ptr es:[di],' '
    jmp stop
s2:
    cmp byte ptr ds:[si],0
    je stop;等于0就跳转
    ;时,分
    mov byte ptr es:[di],':'
    
stop:
    inc si
    add di,2
    loop s
    mov ax,4c00h
    int 21h
    
show:
    push cx
    mov al,ds:[si]
    out 70h,al
    in al,71h
    
    ;获取数据
    mov ah,al
    mov cl,4
    shr ah,cl
    and al,00001111b
    
    ;十进制转ASCII码
    add ah,30h
    add al,30h
    
    ;写入显示缓冲区
    mov es:[di],ah
    mov byte ptr es:[di+2],al
    add di,4
    pop cx
    ret
    
code ends
end start

 

 

第15章 外中断

 15.1 接口芯片和端口

外设的输入不直接送入内存和CPU,而是先送入端口中;CPU向外设的输出也不是直接输入外设,而是先送入端口中,再由相关的芯片送到外设,CPU还可以向外设输出控制信息,而这些控制命令也是先送到相关芯片的端口中,然后再由相关的芯片根据命令对外设实施控制。

可见,CPU通过端口和外部设备进行联系。

15.2 外中断信息

外中断源分为:

  • 可屏蔽中断:CPU可以不响应的外中断。sti,设置IF=1;cli,设置IF=0
  • 不可屏蔽中断:CPU必须响应的外中断。中断类型码固定为2

 

15.3 PC机键盘的处理过程

键盘扫描码

 

KeyDownUpKeyDownUpKeyDownUpKeyDownUp
Esc 1 81 [ { 1A 9A , < 33 B3 center 4C CC
1 ! 2 82 ] } 1B 9B . > 34 B4 right 4D CD
2 @ 3 83 Enter 1C 9C / ? 35 B5 + 4E CE
3 # 4 84 Ctrl 1D 9D R shift 36 B6 end 4F CF
4 $ 5 85 A 1E 9E * PrtSc 37 B7 down 50 D0
5 % 6 86 S 1F 9F alt 38 B8 pgdn 51 D1
6 ^ 7 87 D 20 A0 space 39 B9 ins 52 D2
7 & 8 88 F 21 A1 CAPS 3A BA del 53 D3
8 * 9 89 G 22 A2 F1 3B BB / E0 35 B5
9 ( 0A 8A H 23 A3 F2 3C BC enter E0 1C 9C
0 ) 0B 8B J 24 A4 F3 3D BD F11 57 D7
- _ 0C 8C K 25 A5 F4 3E BE F12 58 D8
= + 0D 8D L 26 A6 F5 3F BF ins E0 52 D2
Bksp 0E 8E ; : 27 A7 F6 40 C0 del E0 53 D3
Tab 0F 8F ' " 28 A8 F7 41 C1 home E0 47 C7
Q 10 90 ` ~ 29 A9 F8 42 C2 end E0 4F CF
W 11 91 L shift 2A AA F9 43 C3 pgup E0 49 C9
E 12 92 \ | 2B AB F10 44 C4 pgdn E0 51 D1
R 13 93 Z 2C AC NUM 45 C5 left E0 4B CB
T 14 94 X 2D AD SCRL 46 C6 right E0 4D CD
Y 15 95 C 2E AE home 47 C7 up E0 48 C8
U 16 96 V 2F AF up 48 C8 down E0 50 D0
I 17 97 B 30 B0 pgup 49 C9 R alt E0 38 B8
O 18 98 N 31 B1 - 4A CA R ctrl E0 1D 9D
P 19 99 M 32 B2 left 4B CB Pause E1 1D 45 E1 9D C5  

-

1.键盘输入

一般按下一个键时产生的扫描码称为通码,松开一个键产生的扫描码称为断码,扫描码长度为一个字节,通码第7位为0,断码第7位为1,即:断码=通码+80h

 

2.引发9号中断

键盘的输入到达60h端口时,相关的芯片就会向CPU发出中断类型码为9的可屏蔽中断信息。CPU检测到该信息后,如果IF=1,则响应中断,否则就会屏蔽中断。

 

3.执行int9中断例程

BIOS键盘缓冲区 它是系统启动后,BIOS用于存放int 9中断历程所接收的键盘输入的内存区。该内存区可以存储15个键盘输入,因为int 9中断例程除了接收扫描码外,还要产生对应的ASCII码,所以,在缓冲区中,一个键盘输入用一个字单元存放,高位扫描码,低位字符码。

 

inc和dec等算术运算指令不影响标志寄存器的中断和调试位

 

15.4 编写int9中断例程

模拟以下几步:

  1. 标志寄存器入栈;
  2. IF=0,TF=0;
  3. CS,IP入栈
  4. (IP)=(DS)*16+0;(CS)=(DS)*16+2

3,4可以简化为call dword ptr ds:[0]

注意:

  1. 该程序要在返回之前,将中断向量表中的int 9中断例程的入口地址恢复为原来的地址,否则程序返回后,别的程序将无法使用键盘。
  2. 取中断码是为了确定程序入口地址,在这里中断码已经确定,所以不能用int指令调用。
assume cs:code
stack segment
    db 128 dup (0)
stack ends
data segment
    dw 0,0
data ends
code segment
start:
    ;栈段地址
    mov ax,stack
    mov ss,ax
    mov sp,128
    
    ;数据段地址
    mov ax,data
    mov ds,ax
    
    ;原9号中断向量表中的入口地址保存到ds:[0],ds:[2]
    mov ax,0
    mov es,ax
    push es:[9*4]
    pop ds:[0]
    push es:[9*4+2]
    pop ds:[2]
    
    ;设置新int9中断例程入口地址
    mov word ptr es:[9*4],offset int9
    mov es:[9*4+2],cs
    
    ;设置显示缓冲区
    mov ax,0b800h
    mov es,ax
    mov di,160*12+40*2
    mov ah,'a'
s:
    ;显示字符
    mov es:[di],ah
    call delay
    inc ah
    cmp ah,'z'
    jna s
    
    ;恢复原来int9中断例程入口地址
    mov ax,0
    mov es,ax
    push ds:[0]
    pop es:[9*4]
    push ds:[2]
    pop es:[9*4+2]
    
    mov ax,4c00h
    int 21h

    ;延时
delay:
    push dx
    push ax
    ;10 0000h写入高地址和低地址
    mov dx,10h
    mov ax,0
s1:
    ;只能使用sub,不能dec
    sub ax,1
    sbb dx,0
    cmp dx,0
    jne s1
    cmp ax,0
    jne s1
    
    pop ax
    pop dx
    ret
    
    ;新中断例程
int9:
    push ax
    push bx
    push es
    ;从60h端口读出键盘的输入
    in al,60h
    
    pushf
    pushf
    ;取出标志寄存器
    pop bx
    ;IF=0,TF=0
    and bh,11111100b
    ;保存标志寄存器
    push bx
    popf
    
    call dword ptr ds:[0];对int指令进行模拟,调用原来的int9中断例程,处理其他硬件细节

    cmp al,1;判断是否按下ESC
    jne int9ret
    
    mov ax,0b800h
    mov es,ax
    inc byte ptr es:[di+1];属性值+1
int9ret:
    pop es
    pop bx
    pop ax
    iret
    
code ends
end start

 

posted @ 2019-07-24 23:05  Hk_Mayfly  阅读(312)  评论(0编辑  收藏  举报