NASM(三)I/O端口和端口访问


I/O端口和端口访问

本质上,端口就是一些寄存器,类似于处理器内部的寄存器。不同之处仅仅在于,这些叫作端口的寄存器位于I/O接口电路中。

端口的不同的实现方式:

  • 端口号是映射到内存地址空间的。比如,0x00000~0xE0000是真实的物理内存地址,而0xE0001~0xFFFFF是从很多I/O接口那里映射过来的,当访问这部分地址时,实际上是在访问I/O接口。
  • 端口是独立编址的,不和内存发生关系。在这种计算机中,处理器的地址线既连接内存,也连接每个I/O接口。但是,处理器还有一个特殊的引脚M/IO#,在这里,“#”表示低电平有效。也就是说,当处理器访问内存时,它会让M/IO#引脚呈高电平,这里,和内存相关的电路就会打开;相反,如果处理器访问I/O端口,那么M/IO#引脚呈低电平,内存电路被禁止。

PATA/SATA的几个端口

  • 命令端口(当向该端口写入0x20时,表明是从硬盘读数据;写入0x30时,表明是向硬盘写数据)
  • 状态端口(处理器根据这个端口的数据来判断硬盘工作是否正常,操作是否成功,发生了哪种错误)
  • 参数端口(处理器通过这些端口告诉硬盘读写的扇区数量,以及起始的逻辑扇区号)
  • 数据端口(通过这个端口连续地取得要读出的数据,或者通过这个端口连续地发送要写入硬盘的数据)

端口指令:

  • in命令,读端口数据:

    • in指令的目的操作数必须是寄存器AL或者AX,当访问8位的端口时,使用寄存器AL;访问16位的端口时,使用AX。in指令的源操作数应当是寄存器DX,用来指定端口号。
    • 例如:in al, dxin ax, dxin ax, 0x01
  • out命令,向端口写:

    • 目的操作数可以是8位立即数或者寄存器DX,源操作数必须是寄存器AL或者AX。
    • 例如:out dx, axout dx, alout 0x01, ax
  • in,out指令不影响任何标志位。

硬盘读取(独立编址)

  • 逻辑扇区编址方法LBA28:使用28比特来表示逻辑扇区号,从逻辑扇区0x0000000到0xFFFFFFF,共可以表示2^28=268435456个扇区。每个扇区有512字节,所以LBA28可以管理128 GB的硬盘。
  • 主硬盘控制器被分配了8位端口,端口号从0x1f0到0x1f7。

    • 设置要读取的扇区数量。这个数值写入0x1f2端口。这是个8位端口。如果写入的值为0,则表示要读取256个扇区。每读一个扇区,这个数值就减1。因此,如果在读写过程中发生错误,该端口包含着尚未读取的扇区数。
    • 设置起始LBA扇区号。扇区的读写是连续的,因此只需要给出第一个扇区的编号。28位的扇区号太长,需要将其分成4段,分别写入端口0x1f3、0x1f4、0x1f5和0x1f6。

      • 0x1f3号端口存放的是0~7位;
      • 0x1f4号端口存放的是8~15位;
      • 0x1f5号端口存放的是16~23位,
      • 0x1f6号端口存放的是24~27位,第4位用于指示硬盘号,0表示主盘,1表示从盘。高3位是“111”,表示LBA模式。
    • 端口0x1f7既是命令端口,又是状态端口。在通过这个端口发送读写命令之后,硬盘开始工作。在它内部操作期间,它将0x1f7端口的第7位置“1”,表明自己很忙。一旦硬盘系统准备就绪,它再将此位清零,同时将第3位置“1”。
    • 0x1f1端口是错误寄存器,包含硬盘驱动器最后一次执行命令后的状态(错误原因)。
    • 0x1f0是硬盘接口的数据端口,16位端口。硬盘准备就绪后,在此端口读取数据。
main:
    mov ax, 0x7c0
    mov ds, ax
    mov ax, 0xf00
    mov es, ax

    mov cx, 10
    xor bx, bx
    mov di, 0
;    call read_disk_one_sector


read_disk_one_sector: ; LBA逻辑扇区号高位存储在bx, 低位存储在cx中, 读取的数据存储在es:di
    ; 向磁盘接口写入读写信息
    mov al, 1
    mov dx, 0x1f2
    out dx, al; 要读取多少个扇区

    mov al, cl
    mov dx, 0x1f3
    out dx, al ; 0x1f3号端口存放的是0~7位

    mov al, ch
    mov dx, 0x1f4
    out dx, al ; 0x1f4号端口存放的是8~15位

    mov al, bl
    mov dx, 0x1f5
    out dx, al ; 0x1f5号端口存放的是16~23位

    mov al, bh
    mov dx, 0x1f6 ; 0x1f6端口的低4位用于存放逻辑扇区号的24~27位,第4位用于指示硬盘号,0表示主盘,1表示从盘。高3位是“111”,表示LBA模式。
    and al, 0b00001111 ; 低四位不变
    or al, 0xe0 ; 高四位置1110
    out dx, al; 0x1f6号端口存放的是24~27位

    ; 写入控制信息, 读
    mov dx, 0x1f7
    mov al, 0x20
    out dx, al

waits:
    in al, dx
    and al, 0x88
    cmp al, 0x08
    jne waits

    mov cx, 256
    mov dx, 0x1f0 ; 0x1f0是硬盘接口的数据端口,且16位端口。
read:
    in ax, dx
    mov [es:di], ax
    add di, 2
    loop read
    jmp near $
    ; 0x1f1端口是错误寄存器
;    ret

end_file:
    times 510-($-$$) db 0
    db 0x55
    db 0xaa

声明:Hello World|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - NASM(三)I/O端口和端口访问


我的朋友,理论是灰色的,而生活之树是常青的!