什么是IN& x86中的OUT指令用于?

时间:2010-07-09 19:23:52

标签: assembly x86 linux-kernel

我已经按照IN& amp; amp; OUT同时阅读“了解Linux内核”一书。我查阅了参考手册。

  

5.1.9 I / O指令

     

这些指令在两者之间移动数据   处理器的I / O端口和a   注册或记忆。

IN    Read from a port
OUT   Write to a port
INS/INSB  Input string from port/Input byte string from port 
INS/INSW  Input string from port/Input word string from port 
INS/INSD  Input string from port/Input doubleword string from port
OUTS/OUTSB    Output string to port/Output byte string to port 
OUTS/OUTSW    Output string to port/Output word string to port 
OUTS/OUTSD    Output string to port/Output doubleword string to port

我没有得到一些东西:

  1. “处理器的I / O端口”。这些是什么?我们为什么要阅读&将“字符串”写入&从这些港口?
  2. 我从来没有遇到过需要使用这些说明的场景。我什么时候需要这些?
  3. 举一些实际的例子。

7 个答案:

答案 0 :(得分:79)

你知道内存寻址是如何工作的吗?有地址总线,数据总线和一些控制线。 CPU将地址总线的字节(或起始字节)的地址放在地址总线上,然后提高READ信号,有些RAM芯片希望通过升高或降低单个行(对应于位)返回该地址的存储器内容在数据总线上的字节中。这适用于RAM和ROM。

但是还有I / O设备:串行和并行端口,PC的微型内置扬声器,磁盘控制器,声音芯片等的驱动程序。这些设备也可以读取和写入。它们还需要被寻址,以便CPU访问正确的设备和(通常)给定设备中的正确数据位置。

对于某些CPU型号,包括大多数“现代”PC中的xxx86系列,I / O设备与内存共享地址空间。 RAM / ROM和IO设备都连接到相同的地址,数据和控制线。例如,COM1的串行端口从(hex)03F8开始寻址。但几乎可以肯定在同一地址有记忆。

这是一个非常简单的图表:

[https://qph.ec.quoracdn.net/main-qimg-e510d81162f562d8f671d5900da84d68-c?convert_to_webp=true]

显然,CPU需要与内存或I / O设备通信,而不是两者都要。为区分这两者,称为“M /#IO”的控制线之一断言CPU是否要与存储器(线路=高电平)或I / O设备(线路=低电平)通信。

IN指令从I / O设备读取,OUT写入。当您使用IN或OUT指令时,M /#IO未置位(保持低电平),因此存储器不响应而I / O芯片也会响应。对于面向内存的指令,M /#IO被置位,因此CPU与RAM通信,IO设备不通信。

在某些条件下,IO设备可以驱动数据线,RAM可以同时读取它们。反之亦然。它被称为DMA。

传统上,串行和打印机端口以及键盘,鼠标,温度传感器等都是I / O设备。盘子介于两者之间;数据传输将由I / O命令启动,但磁盘控制器通常会将其数据直接存入系统内存。

在Windows或Linux等现代操作系统中,对“I / O端口”的访问远离“普通”用户程序,并且存在多层软件,特权指令和驱动程序来处理硬件。所以在本世纪,大多数程序员都不会处理这些指令。

答案 1 :(得分:22)

答案 2 :(得分:11)

举一些实际的例子。

首先学习如何:

然后:

  1. PS/2 controller:将键盘上输入的最后一个字符的扫描码ID设为al

    in $0x60, %al
    

    Minimal example

  2. Real Time Clock (RTC):获取定义秒数的待机时间:

    .equ RTCaddress, 0x70
    .equ RTCdata, 0x71
    
    /* al contains seconds. */
    mov $0, %al
    out %al, $RTCaddress
    in $RTCdata, %al
    
    /* al contains minutes. */
    mov $0x02, %al
    out %al, $RTCaddress
    in $RTCdata, %al
    
    /* al contains hour. */
    mov $0x04, %al
    out %al, $RTCaddress
    

    Minimal example

  3. Programmable Interval Timer (PIT):每0x1234 / 1193181秒生成一个中断号码8:

    mov $0b00110100, %al
    outb %al, $0x43
    mov $0xFF, %al
    out %al, $0x34
    out %al, $0x12
    

    Minimal example

    A Linux kernel 4.2 usage。还有其他人。

  4. 测试:QEMU 2.0.0 Ubuntu 14.04,以及真正的硬件联想ThinkPad T400。

    如何查找端口号:Is there a specification of x86 I/O port assignment?

    https://github.com/torvalds/linux/blob/v4.2/arch/x86/kernel/setup.c#L646列出了Linux内核使用的许多端口。

    其他架构

    并非所有架构都有这样的IO专用指令。

    在ARM中,IO只需写入魔术硬件定义的内存地址即可完成。

    我认为这是https://stackoverflow.com/a/3221839/895245对“内存映射I / O与I / O映射I / O”的含义。

    从程序员的角度来看,我更喜欢ARM方式,因为IO指令已经需要魔术地址来操作,并且我们在64位寻址中有大量未使用的地址空间。

    有关具体的ARM示例,请参阅https://stackoverflow.com/a/40063032/895245

答案 3 :(得分:4)

在硬件级别,大多数微处理器内置很少或没有I / O功能。一些处理器有一个或多个引脚可以使用特殊指令打开和关闭,和/或一个或多个引脚可能是使用特殊分支指令测试,但这种功能很少见。相反,I / O通常通过连接系统来处理,以便访问一系列内存地址将触发某些效果,或者通过包含“in”和“out”指令,其行为类似于内存加载/存储操作,除了特殊信号输出说“这是I / O操作而不是内存操作”。在16位处理器的时代,拥有专门的输入/输出指令曾经有一些真正的优势。如今,这样的优势在很大程度上没有实际意义,因为人们可以简单地将一大块地址空间分配给I / O,并且还有足够的内存空间。

由于程序可能通过不适当地执行I / O指令对系统造成相当大的破坏(例如,这种指令可以执行任意磁盘访问),所有现代操作系统都禁止在用户级代码中使用这些指令。一些系统可以允许这些指令被虚拟化;例如,如果用户代码尝试写入I / O端口0x3D4和0x3D5,则操作系统可能会将其解释为尝试设置某些视频控制控制寄存器以移动闪烁的光标。每次用户程序执行OUT指令时,操作系统都将接管,查看用户程序尝试执行的操作,并采取适当的操作。

在绝大多数情况下,即使操作系统将IN或OUT指令转换为适合的指令,从操作系统直接请求适当的操作也会更有效。

答案 4 :(得分:3)

如果您没有编写操作系统,那么您将永远不会使用这些说明。

基于x86的计算机有两个独立的地址空间 - 您熟悉的内存地址空间,然后是I / O地址空间。 I / O端口地址仅为16位宽,参考低级寄存器和其他低级别小部件是I / O设备的一部分 - 类似于串行或并行端口,磁盘控制器等。

没有实际的例子,因为它们仅供设备驱动程序和操作系统使用。

答案 5 :(得分:1)

它有点诡计多了。它不只是将64kb的单独地址空间复用到具有“额外地址总线/芯片选择引脚”的相同线路上。英特尔8086和8088及其克隆还可以复用数据总线和地址总线; CPU中所有非常罕见的东西。数据表中充满了“最小/最大”配置内容以及您需要连接到它的所有锁存寄存器,以使其“正常”运行。另一方面,它在地址解码中节省了负载和门和“或”门,64kb应该是“每个人都有足够的i / o端口”:P。

此外,对于所有那些“仅限驾驶员开发人员”的人,请注意:除了人们在其他硬件中使用英特尔兼容芯片而不仅仅是PC(他们从来没有真正打算在IBM PC中使用 - IBM刚刚采取因为它们价格便宜且已经上市,所以英特尔还销售具有相同指令集(Intel Quark)的微控制器,并且其他供应商也有大量“片上系统”具有相同的指令集。我不认为你会设法用“用户空间”'内核'和'驱动程序'填入32kb :)。对于大多数事情来说,这种复杂的“操作系在RAM中形成一些UDP数据包然后将它们放入某个环形缓冲区并进行一些中继单击点击不需要30mb内核和10秒加载时间,你知道。它基本上是最好的选择,如果PIC单片机还不够,但你不需要整个工业PC。因此,端口I / O指令确实得到了很多使用,而不仅仅是“驱动程序开发人员”用于更大的操作系统。

答案 6 :(得分:0)

CPU通过io端口连接到某些外部控制器。在旧的x86电脑上我使用I / O端口使用软盘驱动器。如果您知道哪些命令接受设备控制器,您可以通过它的端口对其进行编程。

在现代世界中,您永远不会使用端口指令。如果您是(或将成为)驱动程序开发人员,则例外。

有关于I / O端口http://webster.cs.ucr.edu/AoA/DOS/ch03/CH03-6.html#HEADING6-1

的更多详细信息