• 第十四章 端口


    1、端口的读写
    CPU可以直接读写3 个地方的数据:
    (1)CPU 内部的寄存器;
    (2)内存单元;
    (3)端口。
    对端口的读写不能用mov、push、pop等内存读写指令。

    端口的读写指令只有两条:in 和 out分别用于从端口读取数据和往端口写入数据。

    我们看一下CPU 执行内存访问指令和端口访问指令时候,总线上的信息:
    (1)访问内存
    (2)访问端口

    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端口写入一个字节

    2、CMOS RAM 芯片

    PC机中有一个CMOS RAM芯片,其有如下特征:

    (1)包含一个实时钟和一个有128个存储单元的RAM存储器。(早期的计算机为64个字节)

    (2)该芯片靠电池供电。因此,关机后其内部的实时钟仍可正常工作, RAM 中的信息不丢失。

    (3)128 个字节的 RAM 中,内部实时钟占用 0~0dh单元来保存时间信息,其余大部分分单元用于保存系统配置信息,供系统启动时BIOS程序读取。
    BIOS也提供了相关的程序,使我们可以在开机的时候配置CMOS RAM 中的系统信息。

    (4)该芯片内部有两个端口,端口地址为70h和71h。CPU 通过这两个端口读写CMOS RAM。

    (5)70h为地址端口,存放要访问的CMOS RAM单元的地址;71h为数据端口,存放从选定的CMOS RAM 单元中读取的数据,或要写入到其中的数据。


    3、shl和shr指令
    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,那请问,CF的值是多少捏?

    因为最后移出一位是0,所以CF=0。
    可以看出,将X逻辑左移一位,相当于执行X=X*2。

    shr逻辑右移指令,它和shl所进行的操作刚好相反:
    将一个寄存器或内存单元中的数据向右移位;
    将最后移出的一位写入CF中;
    最高位用0补充。

    编程,用加法和移位指令计算(ax)=(ax)*10
    可以看出,将X逻辑右移一位,相当于执行X=X/2。

    提示:(ax)10=(ax)2+(ax)*8

    assume cs:code

    code segment

    start: mov bx,ax

        shl ax,1   ;左移1位(ax)=(ax)*2
    
        mov cl,3
    
        shl bx,cl       ;左移3位(bx)=(ax)*8
    
        add ax,bx       ;(ax)=(ax)*2+(ax)*8
    
        mov ax,4c00h 
    
        int 21h 
    

    code ends

    end start


    4、CMOS RAM中存储的时间信息
    在CMOS RAM中,存放着当前时间:
    秒:00H
    分:02H
    时:04H
    日:07H
    月:08H
    年:09H
    这6个信息的长度长度都为1个字节。
    这些数据以BCD码的方式存放:
    数码: 0 1 2 3 4
    BCD码: 0000 0001 0010 0011 0100

    数码: 5 6 7 8 9
    BCD码: 0101 0110 0111 1000 1001
    例如:数值26,用BCD码表示为: 0010 0110

    可见,一个字节可表示两个BCD码。

    则CMOS RAM存储时间信息的单元中,存储了用两个 BCD码表示的两位十进制数,高 4 位的BCD码表示十位,低4 位的BCD 码表示个位。

    比如:00010100b表示14。
    课堂作业:编程:在屏幕中间显示当前的月份。
    这个程序主要做两部分工作:
    (1)从CMOS RAM的8号单元读出当前月份的BCD码;(回忆一下)
    要读取 CMOS RAM的信息,我们首先要向地址端口70h写入要访问的单元的地址:
    mov al,8
    out 70h,al
    然后从数据端口71h中取得指定单元中的数据:
    in al,71h
    (2)将用BCD码表示的月份以十进制的形式显示到屏幕上。
    ………………
    …………
    ……
    提示:我们可以看出 ,BCD 码值=十进制数码值,则BCD码值+30h(0的地址)=十进制数对应的ASCII码。
    我们需要进行两步工作:
    (1)将从CMOS RAM的8号单元中读取的一个字节,分为两个表示BCD码值的数据。

    (2)显示(ah)+30h 和 (al)+30 对应的ASCII码字符。

    ;编程:在屏幕中间显示当前的月份

    assume cs:code

    code segment
    start:
    mov al,8
    out 70h,al
    in al,71h
    mov ah,al
    mov cl,4
    shr ah,cl
    and al,00001111b

    	add ah,30h
    	add al,30h
    
    	mov bx,0b800h	;显存
    	mov es,bx
    	mov byte ptr es:[160*12+40*2],ah     ;显示月份的十位数码
    	mov byte ptr es:[160*12+40*2+2],al   ;显示月份的个位数码
    
    	mov ax,4c00h
    	int 21h
    

    code ends
    end start

    编程:以“年/月/日 时:分:秒”的格式,显示当前日期和时间。
    程序一:

    assume cs:code

    code segment

    start: mov ax,0

        mov al,9
    
        mov si,0
    
        mov cx,6
    

    s: push cx

        push ax
    
        out 70h,al        ;将al送入端口70h
    
        in al,71h         ;从端口71h处读出单元内容
    
        mov ah,al
    
        mov cl,4
    
        shr ah,cl
    
        and al,00001111b  ;al分成两个表示BCD码值的数据
    
        add ah,30h
    
        add al,30h        ;BCD码+30h=10进制数对应的ASCII码
    
        mov bx,0b800h
    
        mov es,bx
    
        mov byte ptr es:[160*12+40*2][si],ah     ;显示十位数码
    
        mov byte ptr es:[160*12+40*2+2][si],al   ;显示个位数码
    
        pop ax
    
        dec ax            ;指向前一数据单元
    
        jmp s1
    

    s0: pop cx

        add si,6
    
        loop s
    
        mov ax,4c00h  
    
        int 21h 
    

    s1: cmp ax,10

        ja s0
    
        cmp ax,0
    
        je s0
    
        cmp ax,6
    
        ja s2         ;ax>6,为年/月/日
    
        je s3         ;ax=6,为日结尾
    
        jb s4         ;ax<6,为时:分:秒
    

    s2: mov byte ptr es:[16012+402+4][si],'/' ;添加'/'

        jmp s0
    

    s3: sub ax,2

        jmp s0
    

    s4: sub ax,1

        mov byte ptr es:[160*12+40*2+4][si],':'  ;添加':'
    
        jmp s0
    

    code ends

    end start

    注意:CMOS RAM 中存储着系统的配置信息,除了保存时间信息的单元外,不要向其他的单元中写入内容,否则将引起一些系统错误的~

  • 相关阅读:
    转载--详解tomcat配置
    MongoDB@入门一
    面试@单例模式
    单点登录系统(一)
    SublimeText3 初探(工欲善其事,必先利其器)
    UEFI+GPT 修复 win10启动
    悟空模式-java-建造者模式
    悟空模式-java-原型模式
    悟空模式-java-单例模式
    悟空模式-java-抽象工厂模式
  • 原文地址:https://www.cnblogs.com/poli/p/4722136.html
Copyright © 2020-2023  润新知