用于 x86 输入/输出端口 I/O 的 C inline asm 操作数大小不匹配
Posted
技术标签:
【中文标题】用于 x86 输入/输出端口 I/O 的 C inline asm 操作数大小不匹配【英文标题】:C inline asm for x86 in / out port I/O has operand-size mismatch 【发布时间】:2018-09-16 14:46:54 【问题描述】:我正在关注 youtube 上的教程,他说需要用 C 编写一些 asm 代码(我的汇编不太好),所以我只是处理了整个代码:
unsigned char inPortB (unsigned int _port)
unsigned char rv;
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
return rv;
和
void outPortB (unsigned int _port, unsigned char _data)
__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
但是当我编译我得到这个错误:
operand type mismatch for 'in'
operand type mismatch for 'out'
我该如何解决?
【问题讨论】:
如果您在 Linux 上编码,请考虑使用来自<sys/io.h>
的inb()
和outb()
函数。
@toohonestforthissite :出于性能原因,Linux 有 sys_iopl
和 sys_ioperm
系统调用,允许以 root 权限运行的用户空间程序直接访问在 x86 平台上运行的 Linux 上的端口(通过 IO 权限过程的 TSS)。在用户模式下运行的 XServer 可能会依赖它来进行 8514 图形输出。
@toohonestforthissite sys_iopl
和 sys_ioperm
告诉 x86 Linux(假设一个以 root 权限运行)in
和 out
指令将允许在 Linux 用户模式下直接访问端口 (ring3)不会引起#GP。 x86 硬件在任务状态段中具有 IO 特权位图或 CPLin 和out
端口指令(以及所有相关的端口指令)在特定端口(或所有端口)上作为非特权指令运行。
@G.Sliepen :这似乎是个好主意,但在查看了该标题中的 GLIBC 代码(甚至是他们在 GIT 中拥有的最新版本)之后,这对我来说太严重了在实际项目中考虑。当我打开 sys/io.h 并查看代码时,我感到非常震惊。无论你做什么,都不要在优化的情况下编译它。
@MichaelPetch:哦,我只查看inb
的定义,而不是rep
-string 版本。是的,这太可怕了!您应该在之前的评论中说,只有那些不安全,因为他们的 inb
和 outb
定义没有任何问题,这就是这个问题的 OP 正在使用的。
【参考方案1】:
端口号需要在dx
中,这是一个 16 位寄存器。要使 gcc 生成对 dx
的引用,而不是像处理代码那样生成 edx
,您需要为 _port
提供 16 位类型,例如unsigned short
:
unsigned char inPortB (unsigned short _port)
unsigned char rv;
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
return rv;
这应该可以解决您的问题。
【讨论】:
以上是关于用于 x86 输入/输出端口 I/O 的 C inline asm 操作数大小不匹配的主要内容,如果未能解决你的问题,请参考以下文章
可以在x86汇编中使用IN(以及INS,INSB等)指令块吗?