I am trying to add labels
in C
source code(instrumentation); with a small experience with assembly, comipler is clang
; I have got a strange behavior with __asm__
and labels in CASE
statements !!!;
here is what I have tried:
// 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
IMPORTANT; this will compile successfully with 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 BIT。 任何帮助请..
编辑
根据以下公认的答案:
- The
__asm__
statement itself cause error (different sizes). - The
__asm__
is unreachable. - Adding Label to the statement makes it reachable.
GCC
ignores it.Clang
does not ignore it.
movb
is 8-bit operand-size,%rax
is 64-bit because you usedunsigned long long
. Just usemov
to do a load of the same width as the output variable, or usemovzbl %%gs:%1, %k0
to zero-extend to 64-bit. (Explicitly to 32-bit withmovzbl
, and implicitly to 64-bit by writing the 32-bit low half of the 64-bit register (thek
modifier in%k0
))Surprised GCC doesn't reject that as well; maybe GCC removes it as dead code because of the unreachable
case
inswitch(8)
. If you look at GCC's asm output, it probably doesn't contain that instruction.