Search code examples
assemblyiox86hardware

IN and OUT instructions


i just want to make sure that i got that right.

when i use the IN and OUT instructions in x86.

the CPU sends the port address to the right I/O controller, how does it know which one is the right one ? it knows by looking up the I/O address space, which basically contain a range of port addresses that correspond to an I/O controller.

so let's say the port addresses 0x1000-0x2000 are for the "disk controller"

and the port address 0x3000-0x4000 are for "network controller"

if i send the port address 0x1003 then the cpu will send the port address to the "disk controller".

then the I/O controller receives that port address it then looks up it's internal mapping table in it's memory to determine what register(could also be a memory) of the I/O device is associated with that port address.

then it request to read or write(depends on the instruction) to one of these I/O device registers.


Solution

  • if i send the port address 0x1003 then the cpu will send the port address to the "disk controller".

    Your idea how in and out work is not completely correct:

    I don't know about modern CPUs, but using a simpler CPU (such as the 80386) in and out are variants of the mov instruction accessing different addresses:

    If you see the M/IO pin just as an additional address wire, addresses are 33-bit values, not 32-bit values.

    The instruction out dx, al does exactly the same as a mov [edx], al instruction with only one difference: out dx, al writes to the (33-bit) address [0x100000000+dx] while mov [edx], al writes to the address [edx].

    Now what does the CPU do in this case?

    The CPU uses 33 wires (the address bus) to send the address and 8 wires (the data bus) to send the value of al. It uses additional wires to send the information that some 8-bit value is being written.

    There is some circuit outside the CPU that checks which address is which device:

    This circuit "knows" that addresses 0...0x9FFFF are RAM and when you write to one of these addresses (e.g. you write to address 0x1234 using mov [0x1234],al), the circuit sends an electrical signal to the RAM.

    If you write to address 0x100001234 (e.g. using out dx, al with dx=0x1234), the circuit sends some signal to the disk controller (in your example).

    Let's say the disk controller uses only addresses 0x1000...0x10FF (actually: 0x100001000...0x1000010FF).

    In this case, the disk controller will typically only use the low 8 bits of the address and ignore the other address bits. So if you write to address dx=0x11FF, this has the same effect as writing to address dx=0x10FF.

    In this case, only 8 of the 33 signals holding the address coming from the CPU need to be connected to the disk controller.

    The disk controller receives the following signals:

    • The 8 signals containing the value of al (from the CPU)
    • The 8 low bits of the address being accessed (from the CPU)
    • The signals saying that an 8-bit value is being written (from the CPU)
    • The signal saying that the disk controller is being accessed (from the circuit outside the CPU)