Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C asm错误:";`rol';的操作数类型不匹配&引用;具有多个输入操作数_C_Gcc_Assembly_Operands - Fatal编程技术网

C asm错误:";`rol';的操作数类型不匹配&引用;具有多个输入操作数

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中

环境:Debian 9.5-gcc 6.3.0

当我尝试使用多个
InputOperands
时,无法使嵌入式汇编函数工作

我有以下代码工作(基本
rol
函数,1
inputoroperand
,预定义的
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"
    );
}