我需要从端口读取一些 16 位值并将它们保存到缓冲区。我正在使用的教程建议使用 REP INSW 指令,但我不知道如何使用它,甚至不知道它是如何工作的......
这条指令相当于两条IN指令吗?
最佳答案
答案就在 Intel® 64 and IA-32 Architectures Software Developer’s Manual第一卷:
Section 18.3 I/O ADDRESS SPACE
Any two consecutive 8-bit ports can be treated as a 16-bit port, and any four consecutive ports can be a 32-bit port. In this manner, the processor can transfer 8, 16, or 32 bits to or from a device in the I/O address space. Like words in memory, 16-bit ports should be aligned to even addresses (0, 2, 4, ...) so that all 16 bits can be transferred in a single bus cycle. Likewise, 32-bit ports should be aligned to addresses that are multiples of four (0, 4, 8, ...). The processor supports data transfers to unaligned ports, but there is a performance penalty because one or more extra bus cycle must be used.
如果您查看第 2A 卷指令集引用中的 INSW
指令文档,它会这样说:
INS/INSB/INSW/INSD — Input from Port to String
INS m16, DX Input word from I/O port specified in DX into memory location specified in ES:(E)DI or RDI.
INSW
从 IO 端口空间读取 16 位值到指定的内存地址。 INSW
将从 DX 中指定的指定 PORT 开始读取一个字节,并从 PORT+1 读取一个附加字节,这些字节存储在 ES:E(DI) 和 ES 中:分别为E(DI)+1。
为了回答有关 REP INSW
的问题,REP
将按照 E(CX) 中指定的次数重复此过程。 REP INSW
记录为:
REP/REPE/REPZ/REPNE/REPNZ — Repeat String Operation Prefix
REP INS m16, DX Input (E)CX words from port DX into ES:[(E)DI]
如果您使用REP INSW
从端口 0x1F0 E(CX) 读取 16 位数据,那么您实际上会执行以下操作:
- 从 0x1F0 和 0x1F1 读取 16 位值,并将其存储到 ES:(E)DI 和 ES:(E)DI+1 指向的内存地址。
- 将 E(DI) 加 2。
- 将 E(CX) 减 1。
- 如果E(CX)不为0,则转至步骤1,否则过程结束。
假设您正在编写 32 位代码,然后从端口 0x1F0/0x1F1 读取 16 位 16 次,您可以在 NASM 中将其编码为:
bits 32
; It is assumed that ES is already set and depends on the environment
mov dx, 0x1f0 ; Read words from port 0x1F0 and 0x1F1
mov edi, buffer ; Address of BUFFER
mov ecx, 16 ; Repeat 16 times
rep insw
; Other code and data here
; 16 word buffer (total 32 bytes)
buffer: TIMES 16 dw 0x0000
如果编写 16 位代码,它将类似于:
bits 16
; It is assumed that ES is already set and depends on the environment
mov dx, 0x1f0 ; Read words from port 0x1F0 and 0x1F1
mov di, buffer ; Address of BUFFER
mov cx, 16 ; Repeat 16 times
rep insw
; Other code and data here
; 16 word buffer (total 32 bytes)
buffer: TIMES 16 dw 0x0000
注释
假设您正在运行的环境中,您具有使用端口 IO 指令的权限级别,并且您具有读/写特定 IO 端口的权限。在实模式下没有任何限制。在保护模式、长模式和 v8086 模式下,您可能有也可能没有使用端口指令或访问特定端口的权限的权限级别。您必须查阅操作系统 (OS) 文档,或者如果您正在编写自己的操作系统,则必须使用权限级别/IOPL/IOPL 位图自行设置权限和端口访问限制。
rep insw
还可以使用操作数大小前缀在 64 位模式下使用(NASM 将通过添加 0x66 前缀来处理编码)。计数将以 RCX 为单位,ES 段不适用:REP INS r/m32, DX Input RCX default size from port DX into [RDI].
关于assembly - REP INSW 做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57944636/