C asm错误:";`rol';的操作数类型不匹配&引用;具有多个输入操作数
环境:Debian 9.5-gcc 6.3.0 当我尝试使用多个C asm错误:";`rol';的操作数类型不匹配&引用;具有多个输入操作数,c,gcc,assembly,operands,C,Gcc,Assembly,Operands,环境:Debian 9.5-gcc 6.3.0 当我尝试使用多个InputOperands时,无法使嵌入式汇编函数工作 我有以下代码工作(基本rol函数,1inputoroperand,预定义的rol操作数): gcc返回错误: resolve.c: Assembler messages: resolve.c:6: Error: operand type mismatch for `rol' 我用int8\u t和int32\u t尝试了I,它没有改变任何东西 我必须说,在这种环境中,我对C中
InputOperands
时,无法使嵌入式汇编函数工作
我有以下代码工作(基本rol
函数,1inputoroperand
,预定义的rol
操作数):
gcc返回错误:
resolve.c: Assembler messages:
resolve.c:6: Error: operand type mismatch for `rol'
我用int8\u t
和int32\u t
尝试了I
,它没有改变任何东西
我必须说,在这种环境中,我对C中的嵌入式asm是新手,我只在Windows上用Visual Studio完成了一些基本的内联汇编。正如Michael Petch在评论中所说 控制移位位数的移位指令所允许的唯一寄存器是CL 他还提供了以下解决方案: c表示使用CL寄存器(假设将变量i的类型更改为int8_t而不是int16_t)。大写字母(i)表示约束也可以是介于0和32之间的立即值 正如Michael Petch和Peter Cordes在评论中指出的,我的代码不起作用,因为我使用
%1
作为rol
操作数,但正确的变量是%2
。我犯了这个错误,因为我认为%\code>只引用了输入和
Michael Petch和Peter Cordes还提供了一些很好的文档:
(…)机器约束可在此处找到:在i386信息下
没有理由使用内联asm进行旋转
调试内联asm时,您应该查看编译器生成的asm,以查看它在模板中替换了什么。例如,这很方便:。您甚至可以执行nop#%0%1%2之类的操作,以查看编译器为所有操作数选择了什么,无论您是否在模板中引用它们。有关更多指南和示例,请参见
因为控制移位位数的移位指令所允许的唯一寄存器是CL.void asm_roll(int32_t*p_rolled,int8_ti){uu asm_volatile(.intel_语法noprefix;“.rol%0,%1;”:“+a”(*p_rolled):“cI”(i):“cc”)}
可能会起作用,因为%1
可能是%2
。%2表示它映射到第三个约束。约束编号基于0(0=1,1=2,2=3)@NdFeB:因为该asm语句中的移位计数是%2
。使用命名约束,如asm(“rol%0,%[count]”,等等,[count]“cI”(i));
并使用“+r”
对于读写输入/输出操作数;没有理由强制编译器使用EAX/RAX。无论如何,所有这些都比纯C更糟糕,因为它会破坏常量传播和其他可能的优化。在调试内联asm时,您应该查看编译器生成的asm,看看它在模板中替换了什么。e。g、 非常方便:。您甚至可以执行类似nop#%0%1%2
的操作,以查看编译器为所有操作数选择了什么,无论您是否在模板中引用它们。有关更多指南和示例,请参见。您已努力编写注释并格式化注释,这对我来说非常好。继续并接受您自己的编写在2天内。您不需要将此asm语句设置为易变的。。如果从未使用新值*p\u rolled
,您希望将其优化掉。或者,如果相同的值以相同的计数旋转多次,则将其从循环中提升出来。“cc”
clobbers对于i386和x86-64上的内联asm是隐式的。如果您看到没有clobbers的示例,则没有错;将其添加到中纯粹是可选的。您的.intel\u syntax noprefix
将破坏任何编译生成的代码,除非编译器已经通过使用-masm=intel
.I编译发出英特尔语法代码如果你想让它在没有-masm=intel
的情况下工作,你需要用.att_syntax
恢复AT&T语法。但是如果你用-masm=intel
编译,它就会崩溃。你可以用asm方言替代,比如{%0,%1 |%1,%0}
在本例中,要使其同时适用于这两种情况。但通常人们在GNU C内联asm中使用AT&T语法。至少Linux内核是这样做的。在您自己的项目中,您可以做任何事情。@NdFeB如果没有输出操作数,则volatile是隐式的。因为所有更改都在输入和输出操作数中捕获,并且没有其他副作用也可以消除。对额外的volatile进行优化后,可能会在不需要的时候强制生成代码。如果你想变得更有趣,还有asm(“roll%[value],%[rollby]:[value]:“+a”(*p_rolled):[rollby]“cI”(i):“cc”)
像这样使用符号名在这样的一行asm中可能没有多大区别。但是如果事情变得更复杂,不必一直查看“哪一个是%2?”是很好的,如果您最终需要添加或删除参数,这真的很好。必须对所有内容重新编号很讨厌。我还可以更改“+a”
只需“+r”
。正如Peter所说,如果编译器有其他更好的寄存器,则无需强制eax。
#include <stdio.h>
#include <stdlib.h>
void asm_rol(int32_t* p_rolled, int16_t i)
{
__asm__ volatile
(
".intel_syntax noprefix;"
"rol %0, %1;"
:"=a"(*p_rolled)
:"a"(*p_rolled), "b"(i)
:"cc"
);
}
int main(int argc, char** argv)
{
int32_t test = 0x1;
asm_rol(&test, 1);
printf("0x%08x\n", test);
return 0;
}
resolve.c: Assembler messages:
resolve.c:6: Error: operand type mismatch for `rol'
void asm_rol(int32_t* p_rolled, int8_t i) {
__asm__ volatile
(
".intel_syntax noprefix;"
"rol %0, %1;"
:"+a"(*p_rolled)
:"cI"(i) :"cc"
);
}