简体   繁体   中英

Why is the THUMB instruction “mov r0, #0” not allowed?

I'm attempting to figure out some ARM assembly for an STM32 microcontroller. When I try to assemble the instruction mov r0, #0 , I get:

core.S:27: Error: cannot honor width suffix -- `mov r0,#0'

yet it works when I use movs r0, #0 . Here , it says that the "s" only affects whether condition flags are updated.

I have a similar problem with add r0, r0, #1 vs adds r0, r0, #1 .

Can someone please explain why movs works and mov doesn't?

So currently within the STM32 world you have four different instruction sets based on armv6m, armv7m and armv8m. Technically for now the armv8m baseline matches armv6m and armv8m mainline extensions matches armv7m.

So the armv6m instruction set in theory works for all cortex-ms at this time and it uses the tranditional all thumb variants (going back to armv4t's thumb instruction set) add and mov.

.cpu arm7tdmi
.thumb
.syntax unified
mov r1,#1
movs r1,#1

so.s: Assembler messages:
so.s:4: Error: cannot honor width suffix -- `mov r1,#1'

.cpu arm7tdmi
.thumb
.syntax unified
movs r1,#1
movs r1,#1

Disassembly of section .text:

00000000 <.text>:
   0:   2101        movs    r1, #1
   2:   2101        movs    r1, #1

.cpu cortex-m0
.thumb
.syntax unified
mov r1,#1
movs r1,#1

so.s: Assembler messages:
so.s:4: Error: cannot honor width suffix -- `mov r1,#1'

.cpu cortex-m3
.thumb
.syntax unified
mov r1,#1
movs r1,#1

Disassembly of section .text:

00000000 <.text>:
   0:   f04f 0101   mov.w   r1, #1
   4:   2101        movs    r1, #1

Now the ARMv7m document says this:

Encoding T1  All versions of the Thumb instruction set.
MOVS <Rd>,#<imm8>  Outside IT block.
MOV<c> <Rd>,#<imm8> Inside IT block.

armv6m does not have the it instruction so this is a touch misleading, the movs encoding is supported by all thumb variants, but not the other.

.cpu cortex-m3
.thumb
.syntax unified

itt ne
movne r1,#1
mov r1,#2
mov r1,#3

so.s: Assembler messages:
so.s:7: Error: instruction not allowed in IT block -- `mov r1,#2'

so you cannot use it there either.

.cpu cortex-m3
.thumb
.syntax unified

itt ne
movne r1,#1
movsne r1,#2
mov r1,#3

Disassembly of section .text:

00000000 <.text>:
   0:   bf1c        itt ne
   2:   2101        movne   r1, #1
   4:   f05f 0102   movsne.w    r1, #2
   8:   f04f 0103   mov.w   r1, #3

The short answer is that you cannot because the instruction does not exist. If you are using unified syntax documentation that glosses over which instruction sets are supported, then you have, as many others, fallen into the trap of the major failing of the unified syntax. A pretty serious oops, on ARM's part. Just have instruction sets like every one else, done.

stm32 is too broad you have cortex-m0, m0+, m3, m4, m7, and flavors of m8. m0 and m0+ and some m8's are basically armv6m and this instruction is not supported in any way. The m3,m4,m7 and some m8's it is as a thumb2 extension or with a condition specification within an it block.

With the unified syntax and thumb it is best to add the s unless you definitely do not want it then hope for the best.

If you are using the original gnu assembler thumb syntax, then, thanks to I assume a combination of ARM's documentation (at that time) and the gnu folks, you can't have the s (for some instructions)

.arch armv5t
.thumb
mov r1,#3
movs r1,#3
add r1,r2,r3
adds r1,r2,r3

so.s: Assembler messages:
so.s:6: Error: instruction not supported in Thumb16 mode -- `adds r1,r2,r3'
.arch armv5t
.thumb
.syntax unified
mov r1,#3
movs r1,#3
add r1,r2,r3
adds r1,r2,r3

so.s: Assembler messages:
so.s:4: Error: cannot honor width suffix -- `mov r1,#3'
so.s:6: Error: cannot honor width suffix -- `add r1,r2,r3'

And last but not least, assembly language (the syntax) is specific to the tool (the assembler) not the target (arm/thumb). So all of the above is gnu assembler for many of the versions that support various flavors of the thumb instruction sets. You can look at armasm (tool from ARM not GNU) as well as perhaps others, and their rules may vary. So within armasm it may very well be proper syntax as the mov r1,#1 shown in these last examples

.arch armv5t
.thumb
mov r1,#3
movs r1,#3
add r1,r2,r3

Disassembly of section .text:

00000000 <.text>:
   0:   2103        movs    r1, #3
   2:   2103        movs    r1, #3
   4:   18d1        adds    r1, r2, r3

indicates. (also note the disassembler folks and assembler folks disagree as well, I do not have a binutils from the pre-unified-syntax era to see what it showed).

ARM's documentation is going to be either specific to no tool as the authors of the architecture are different than the tool creator/maintainers. Or they may attempt to get along and have the architecture documents match their internal tools. But that in no way means gnu has to conform and sadly people that port targets to gnu assembler seem to have a habit of not supporting the processor vendors syntax completely, there is often a painful or annoying twist.

(How you read that ARM ARM, you could have used the s option as it shows the arm equivalent, with the s option, the defined syntax in the doc did not show that so depending on the assembler author, they had to pick one or make up some syntax).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM