asm error: "operand type mismatch for `rol'" with multiple input operands

asm error: "operand type mismatch for `rol'" with multiple input operands

环境:Debian 9.5 - gcc 6.3.0

当我尝试使用多个 InputOperands.

时,我无法使嵌入式汇编函数工作

我有以下代码工作(基本 rol 函数,1 InputOperand,预定义 rol 操作数):

#include <stdio.h>
#include <stdlib.h>

void asm_rol(int32_t* p_rolled)
{
    __asm__ volatile
    (
        ".intel_syntax noprefix;"
        "rol %0, 1;"
        :"=a"(*p_rolled)
        :"a"(*p_rolled)
        :"cc"
    );
}

int main(int argc, char** argv)
{
    int32_t test = 0x1;
    asm_rol(&test);

    printf("0x%08x\n", test);
    return 0;
}

这会打印 0x00000002,并且是 rol 0x1, 1 的正确结果。

现在我不明白为什么下面的代码不能编译。我认为我对 InputOperands 的用法很糟糕:

#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;
}

gcc returns 错误:

resolve.c: Assembler messages:
resolve.c:6: Error: operand type mismatch for `rol'

我尝试将 int8_tint32_t 用于 i,它没有改变任何东西。

我必须说我是在这种环境下使用 C 语言嵌入汇编的新手,我只在 Windows 上用 Visual Studio 做过一些基本的内联汇编。

正如 Michael Petch 在评论中所说,

the only register that is allowed for a shifting instruction that controls the number of bits to shift is CL

他还提供了以下解决方案:

void asm_rol(int32_t* p_rolled, int8_t i) {
    __asm__ volatile
    (
        ".intel_syntax noprefix;"
        "rol %0, %1;"
        :"+a"(*p_rolled)
        :"cI"(i) :"cc"
    );
}

The c says to use the CL register (assuming you change the type of variable i to int8_t instead of int16_t. . The Capital-Eye (I) says the constraint can also be an immediate value between 0 and 32.

正如 Michael Petch 和 Peter Cordes 在评论中指出的那样,我的代码无法正常工作,因为我使用 %1 作为 rol 操作数,但正确的变量是 %2 .我犯了这个错误,因为我认为只有 InputOperands%#.

引用了

Michael Petch 和 Peter Cordes 也提供了一些不错的文档:

(...) machine constraints can be found here: gcc.gnu.org/onlinedocs/gcc/… under the i386 info

There's no reason to use inline asm for rotates. Best practices for circular shift (rotate) operations in C++

When debugging inline asm, you should look at the compiler-generated asm to see what it substituted into the template. e.g. godbolt.org is handy: . You can even do stuff like nop # %0 %1 %2 to just see what the compiler picked for all the operands, whether you reference them in the template or not. See also whosebug.com/tags/inline-assembly/info for more guides and examples.