GCC内联组件';Nd';约束

GCC内联组件';Nd';约束,gcc,x86,kernel,inline-assembly,osdev,Gcc,X86,Kernel,Inline Assembly,Osdev,我正在用C语言开发一个小玩具内核。我现在需要从键盘获取用户输入。到目前为止,我已经使用以下代码实现了inb: static inline uint8_t inb(uint16_t port) { uint8_t ret; asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); return ret; } 我知道“=a”约束意味着al/ax/eax将作为输出复制到ret,但我仍然对“Nd”约束感到困惑。有人能提供一些

我正在用C语言开发一个小玩具内核。我现在需要从键盘获取用户输入。到目前为止,我已经使用以下代码实现了
inb

static inline uint8_t inb(uint16_t port) {
     uint8_t ret;
     asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
     return ret;
}

我知道
“=a”
约束意味着
al/ax/eax
将作为输出复制到
ret
,但我仍然对
“Nd”
约束感到困惑。有人能提供一些关于为什么需要这个约束的见解吗?或者为什么我不能只使用像
“r”
“b”
这样的通用寄存器约束?任何帮助都将不胜感激。

中的
指令(返回一个字节)可以采用立即8位值作为端口号,也可以采用
dx
寄存器中指定的端口。有关
中的
指令的更多信息,请参见(英特尔语法)。正在使用的机器约束可以在中找到。如果向下滚动到x86系列
,您将看到:

d

N

Unsigned 8-bit integer constant (for in and out instructions). 

你的目标是16位代码吗?我的目标是32位代码,因为我使用GRUB将内核加载到保护模式。好的,谢谢。这帮了大忙。但是,我还有最后一个问题,如果
N
约束只允许0-255之间的端口使用立即字节,而
d
约束允许整个
dx
寄存器,为什么我不只使用
d
约束?我的意思是,使用这两种约束的优点是什么?@MichaelMorrow这是8086/8088年代的一个延期,当时节省空间通常很重要。如果使用8位立即数(对于0-255之间的端口),则不需要额外的指令将其首先移动到
DX
(节省空间)。如果要访问端口256-65535,必须将其传入
DX
。您可以在
DX
中指定一个8位(0-255)端口号,但必须先将其移动到
DX
中,这会在空间上造成额外的惩罚。@MichaelMorrow如果您使用“Nd”作为约束进行优化(-O1,-O2,-O3)编译,如果汇编器模板看到传递的值可以容纳8位并编码较小的版本(无需先移动到
DX
),则会向编译器发出提示。如果您只使用了“d”,那么就没有提示编译器可以优化模板中的汇编代码,并且将使用较长的形式(无论是否需要
DX
)。几分钟后我会用这些信息更新我的答案。
Unsigned 8-bit integer constant (for in and out instructions).