理解GCC内联汇编语法中的输入/输出操作数

3
作为编写操作系统的一部分,我正在实现中断处理和I/O函数inboutb
我不得不学习在GCC中编写内联汇编,并在线上阅读了很多相关资料。根据我的理解,我编写了自己的代码。同时,我查阅了Linux在/usr/include/sys/io.h中对这些函数的实现。下面是outb的代码:
static __inline void
outb (unsigned char __value, unsigned short int __port)
{
  __asm__ __volatile__ ("outb %b0,%w1": :"a" (__value), "Nd" (__port));
}

这是我的问题:
GCC手册说“N”是
无符号8位整数常量(用于in和out指令)。
但是这里的__port是unsigned short int,我认为应该是16位。那么如何决定使用16位中的哪一部分作为内联汇编代码的参数?
以下是我的工作原理:__port的值将直接用作%w1的常量(因为有“N”)。 __value的值复制到eax中。%bo被替换为%al。然后执行指令。这样正确吗?
如何决定使用第二个操作数的“N”或“d”? 是否有某种偏好顺序?
如果我不使用“N”,会有什么区别?不仅仅使用“d”是否更好,因为它是16位?
如果我省略了“N”,那么__port的值是否正确复制到edx中,然后将%w1替换为edx?
1个回答

2
我可能理解有误,但我认为"Nd"的意思是在编译器的偏好下使用Nd。如果该值不是已知适合8位的常量,则无法满足N,因此编译器别无选择,只能使用d。但当该值是编译时常量且其值适合8位时,使用8位立即数比浪费寄存器更可取。

这很有道理。不过,至少对于初学者来说,它应该在手册中提到。你能否也谈一下其他问题? - Cygnus
1
猜猜看,它在手冊中:"最简单的约束是一个由字母组成的字符串,每个字母描述了一种允许的操作数类型。" - Jester

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接