Does this:
mov al, 0ffh
in al, dx
always do the same as this:
in al, dx
So, is the mov al, 0ffh
redundant, and does an in al, dx
instruction always set the value of AL, never keeping the previous value?
If there are differences within the CPU product line (8086, 186, 286, 386, 486, Pentium and beyond), please highlight them.
in al, dx
always over writes AL, same as mov al, src
.
Unless it faults, in which case AL has its previous value when the CPU jumps to the fault handler.
In protected mode, user-space can't run I/O instructions like in
unless the IO privilege level is elevated to 0
, or if specific ports are allowed in an I/O bitmap. (Linux ioperm(2)
to allow specific ports in a limited range, iopl(2)
to change IO privilege level). IO privilege level is separate from the current privilege level in the low bits of the CS selector, so e.g. you can let user-space run cli
on this core (potentially getting it stuck other than NMIs) without letting it run invd
and break cache coherency system-wide.
So anyway, faulting with #GP(0)
due to privilege level is one way for in
to fault. Apparently (https://www.felixcloutier.com/x86/in#64-bit-mode-exceptions) it can also fault with #PF in protected or 64-bit mode. The description section doesn't say how; the port number is in I/O address-space so isn't translated. I wonder if maybe this entry used to also document (rep
) ins
which writes to ES:rDI
and thus can #PF on the memory destination, and maybe they forgot to take out #PF
when splitting ins
to its own entry.
Protected mode was new in 286, and 386 changed it a bit.
In real mode, it can't fault other than with #UD
(if lock
prefix is used).