我觉得x86-64的gcc 约束符`A',存在语义上的BUG
理由:
gcc为什么要允许程序员指定某个(些)寄存器? 因为CPU有些指令会隐式的使用这个(些)寄存器。
不然的话,直接指定`r'不就得了?
IA32的几条指令rdtsc, rdmsr, rdpmc, wrtsc, wrpmc, wrmsr, 读写的是一个64位操作数,高32位在edx中,低32位在eax中。
因此,gcc for ia32的约束符`A'的含义就是edx:eax。
x86-64的这几条指令,语法、语义上和IA32的完全相同。 但诡异的是,gcc for x86-64的约束符`A'的语义却是: rax或rdx!
试问程序为什么需要这个`A'? 完全没有理由嘛, 没有任何一条指令使用{rax, rdx}做隐式的操作数。 而如果只需要一个普通
的64位GPR,那么`R'或`r'就好了,为什么需要A?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
gcc在IA32中为了使用64位寄存器,使用了约束符`A',就是edx:eax。
x86-64中的约束符`A'为了保持语义的一致,即提供64位寄存器,继续采用edx:eax或者采用新的rax、rdx是实现的不同,语义上仍然是相同的啊。A就是64位寄存器,没变啊?
从兼容上考虑,64位的A应该是什么含义呢?128位寄存器?也许x86和x64的维护者认为从edx:eax过渡到rax或者rdx比较方便实现。纯属猜测,maillist上问问最保险了。
有啊,div指令和mul指令
64位的A是rax *或* rdx, 但是我只能试验到rax中,没办法试验gcc是否会选择rdx。
之所以这么说,是因为info手册里的暗示。
Duh - 忘了这个。
32位的native_read_msr函数可以这么写:
#define read_msr(msr) \
{ unsigned long long val; asm volatile ("rdmsr": "=A" (val) : "c"(msr) ); \
val; }
而64位的则不行。 CPU的指令语义没有变化,但是gcc的“A”变了。 只能写成:
#define read_msr(msr) \
{ unsigned long long val; unsigned int eax, edx; asm volatile ("rdmsr": "=a" (eax), "=d" (edx): "c" (msr) ); \
val = ((unsigned long long) edx ) << 32 | eax; \
val; }
不清楚,向你学习。
要不问问x64backend的维护者吧。
有些情况下对特定的寄存器有些需要,例如,我希望程序自始至终或者一段时间内不要用某个寄存器,因为里面记录了一个重要的数据。
所谓的制定也是告诉编译器用什么样的寄存器,而不是完全指定的。
如果要用则需要对这样的语法很熟悉才行,否则就很郁闷。