首页 > 解决方案 > clang __asm__ 在 case 语句中带有标签,得到错误:指令的操作数无效

问题描述

我正在尝试添加labelsC代码(仪表);有一点汇编经验,编译器是clang;我在语句中有一个奇怪的行为__asm__和标签CASE!!!; 这是我尝试过的:

// Compiles successfully.
int main()
{
     volatile unsigned long long a = 3;
      switch(8UL)
      {
         case 1UL:
            //lbl:;
            __asm__ ("movb %%gs:%1,%0": "=q" (a): "m" (a));
            a++;
      }
    return 0;
}

还有这个 :

// Compiles successfully.
int main()
{
     volatile unsigned long long a = 3;
      switch(8UL)
      {
         case 1UL:
            lbl:;
            //__asm__ ("movb %%gs:%1,%0": "=q" (a): "m" (a));
            a++;
      }
    return 0;
}

命令:

 clang -c examples/a.c
examples/a.c:5:14: warning: no case matching constant switch condition '8'
      switch(8UL)
             ^~~
1 warning generated.                  

但是这个:

// not Compile.
int main()
{
     volatile unsigned long long a = 3;
      switch(8UL)
      {
         case 1UL:
            lbl:;
            __asm__ ("movb %%gs:%1,%0": "=q" (a): "m" (a));
            a++;
      }
    return 0;
}

错误:

             ^~~
examples/a.c:9:22: error: invalid operand for instruction                                                                                                                                     
            __asm__ ("movb %%gs:%1,%0": "=q" (a): "m" (a));
                     ^
<inline asm>:1:21: note: instantiated into assembly here                                                                                                                                      
        movb %gs:-16(%rbp),%rax
                           ^~~~
1 warning and 1 error generated. 

我在用 :

clang --version
clang version 9.0.0-2 (tags/RELEASE_900/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

重要的; 这将使用gcc.

gcc --version
gcc (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

我正在使用 Ubuntu 19 ,64 位。任何帮助请..


编辑

根据以下接受的答案:

标签: clangx86-64inline-assemblyatt

解决方案


movb is 8-bit operand-size, %rax is 64-bit because you used unsigned long long. Just use mov to do a load of the same width as the output variable, or use movzbl %%gs:%1, %k0 to zero-extend to 64-bit. (Explicitly to 32-bit with movzbl, and implicitly to 64-bit by writing the 32-bit low half of the 64-bit register (the k modifier in %k0))

Surprised GCC doesn't reject that as well; maybe GCC removes it as dead code because of the unreachable case in switch(8). If you look at GCC's asm output, it probably doesn't contain that instruction.


推荐阅读