适用于 gcc 但不适用于 clang 的汇编代码

Assembly code that works for gcc but not for clang

我使用 arm arch 的 gcc 编译器得到了这段代码 arm-none-eabi-gcc -c s.s

.arch armv6-m
.thumb_func
MOVS  r0, lr
MOVS  r1, #0xF
AND   r0, r1

当我尝试 assemble 它使用 clang 作为手臂拱形时 clang --target=arm-none-abi -c s.s 我遇到了这些错误

s.s:3:13: error: invalid operand for instruction
MOVS  r0, lr
            ^
s.s:5:1: error: invalid instruction
AND   r0, r1
^

我试图取消assemble 工作的 gcc 输出,我发现它将 MOVS 转换为 MOV 并将 AND 转换为 ANDS

$ arm-none-eabi-objdump -S s.o

s.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
   0:   4670        mov r0, lr
   2:   210f        movs    r1, #15
   4:   4008        ands    r0, r1

所以我将代码更改为类似于 assembled 的代码并再次重新运行 clang 并且它通过了很好但是当我重新运行 gcc 时我得到了这个错误

s.s:5: Error: instruction not supported in Thumb16 mode -- `ands r0,r1'
  1. 尽管 gcc assembler 将它从 AND 更改为 ANDS 并且之前可以工作,但为什么不支持该指令? clang 接受了吗?
  2. 还有为什么 gcc assembler 将 MOVS 更改为 MOV?
  3. 如何获得适用于两种编译器的通用代码?
.arch armv6-m
.thumb
mov r0,lr

arm-none-eabi-gcc -c test.s -o test.o
arm-none-eabi-objdump -D test.o

test.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
   0:   4670        mov r0, lr

(为 armv6-m 构建的 clang)

clang test.s -c -o test.o
arm-none-eabi-objdump -d test.o

test.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
   0:   4670        mov r0, lr

但是有了 movs

.arch armv6-m
.thumb
movs r0,lr

arm-none-eabi-gcc -c test.s -o test.o
arm-none-eabi-objdump -d test.o

test.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
   0:   4670        mov r0, lr

(回到第一个拇指支持,汇编器可以自由地做他们想做的事)

clang test.s -c -o test.o
test.s:4:1: error: invalid instruction, any one of the following would fix this:
movs r0,lr
^
test.s:4:9: note: operand must be an immediate in the range [0,255]
movs r0,lr
        ^
test.s:4:9: note: operand must be a register in range [r0, r7]
movs r0,lr
        ^

现在这个

.arch armv6-m
.thumb
.syntax unified
movs r0,lr

arm-none-eabi-gcc -c test.s -o test.o
test.s: Assembler messages:
test.s:5: Error: cannot honor width suffix -- `movs r0,lr'

(只因为这是armv6-m不是armv7-m)

clang test.s -c -o test.o
test.s:5:1: error: invalid instruction, any one of the following would fix this:
movs r0,lr
^
test.s:5:9: note: operand must be an immediate in the range [0,255]
movs r0,lr
        ^
test.s:5:9: note: operand must be a register in range [r0, r7]
movs r0,lr

还有这个

.arch armv6-m
.thumb
.syntax unified
mov r0,lr

arm-none-eabi-gcc -c test.s -o test.o
arm-none-eabi-objdump -d test.o

test.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
   0:   4670        mov r0, lr

clang test.s -c -o test.o
arm-none-eabi-objdump -d test.o

test.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
   0:   4670        mov r0, lr

你的代码

.arch armv6-m
.thumb_func
movs r0,lr

arm-none-eabi-gcc -c test.s -o test.o
arm-none-eabi-objdump -d test.o

test.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
   0:   4670        mov r0, lr

又是低级趣味,但汇编程序可以为所欲为。

我是正确的。thumb_func 有趣的是在这里做了一些事情

.arch armv6-m
movs r0,lr

没有意义,但是哦好吧...

arm-none-eabi-gcc -c test.s -o test.o
test.s: Assembler messages:
test.s:3: Error: attempt to use an ARM instruction on a Thumb-only processor -- `movs r0,lr'

嗯...

.arch armv6-m
mov r0,lr

arm-none-eabi-gcc -c test.s -o test.o
test.s: Assembler messages:
test.s:3: Error: attempt to use an ARM instruction on a Thumb-only processor -- `mov r0,lr'

没有。

ARM统一语法.syntax unified解决Thumb16模式下ANDS不支持指令,gcc错误。根据 gnu binutils documents,统一语法具有此功能:所有指令设置标志当且仅当它们具有 s 词缀时。

所以适用于 gcc 和 clang 的最终通用代码是:

.arch armv6-m
.syntax unified
.thumb_func

MOV  r0, lr
MOVS r1, #0xF
ANDS r0, r1