Search code examples
assemblyarmthumb

ARM assembler transfers Thumb instructions into Thumb2


Whenever I compile the following program:

.syntax unified
.section .text
_start:
ADD R0, R1

I get the following binary output:

ADD.W R0, R0, R1

which means my assembler transfers the 16 bit code to 32 bit code. I wonder why my assembler behaves like that instead of compiling the code to the 16 bit instruction "08 44"

I run the assembly with the following command:

arm-none-eabi-as -o output.o -m thumb -EL input.s


Solution

  • add r0,r1
    adds r0,r1
    adds r8,r0
    
    arm-none-eabi-as -mthumb  so.s -o so.o
    so.s: Assembler messages:
    so.s:2: Error: instruction not supported in Thumb16 mode -- `adds r0,r1'
    so.s:3: Error: instruction not supported in Thumb16 mode -- `adds r8,r0'
    

    interesting

    add r0,r1
    add r0,r1
    add r8,r1
    
    00000000 <.text>:
       0:   1840        adds    r0, r0, r1
       2:   1840        adds    r0, r0, r1
       4:   4488        add r8, r1
    

    interesting.

    .thumb
    .syntax unified
    
    add r0,r1
    add r0,r1
    add r8,r1
    
    00000000 <.text>:
       0:   eb00 0001   add.w   r0, r0, r1
       4:   eb00 0001   add.w   r0, r0, r1
       8:   4488        add r8, r1
    

    okay progress

    .thumb
    .syntax unified
    
    add r0,r1
    adds r0,r1
    adds r8,r1
    
    00000000 <.text>:
       0:   eb00 0001   add.w   r0, r0, r1
       4:   1840        adds    r0, r0, r1
       6:   eb18 0801   adds.w  r8, r8, r1
    

    hmmm.

    .thumb
    .syntax unified
    
    add r0,r1
    adds r0,r1
    add r8,r1
    
    00000000 <.text>:
       0:   eb00 0001   add.w   r0, r0, r1
       4:   1840        adds    r0, r0, r1
       6:   4488        add r8, r1
    

    okay that is just disturbing.

    .thumb
    .syntax unified
    
    add r0,r1
    adds r0,r1
    add.w r8,r1
    
    00000000 <.text>:
       0:   eb00 0001   add.w   r0, r0, r1
       4:   1840        adds    r0, r0, r1
       6:   eb08 0801   add.w   r8, r8, r1
    

    So getting the 0x18xx and 0x44xx instruction to generate is not to hard. the assembler doesnt make life easy. if you want a specific instruction you should just put the machine code in there and be done with it.

    EDIT, sigh tried Notlikethat's suggestion

    .thumb
    .syntax unified
    
    add.n r0,r1
    add.n r8,r1
    
    arm-none-eabi-as -mthumb so.s -o so.o
    so.s: Assembler messages:
    so.s:5: Error: cannot honor width suffix -- `add.n r0,r1'
    

    fail

    .thumb
    
    add.n r0,r1
    add.n r8,r1
    
    arm-none-eabi-as -mthumb so.s -o so.o
    so.s: Assembler messages:
    so.s:4: Error: unexpected character `n' in type specifier
    so.s:4: Error: bad instruction `add.n r0,r1'
    so.s:5: Error: unexpected character `n' in type specifier
    so.s:5: Error: bad instruction `add.n r8,r1'
    

    fail

    .thumb
    .syntax unified
    
    adds.n r0,r1
    add.n r8,r1
    
    00000000 <.text>:
       0:   1840        adds    r0, r0, r1
       2:   4488        add r8, r1
    

    okay that got it...

    and the add vs adds, makes sense too, for whatever reason the high register version of the add the 0x44xx one you were after does not modify the flags where the 0x18xx low register one does. The ascii assembly language in the ARMv7-m ARM shows this.

    EDIT 2, an older arm arm says

    Operand restriction If a low register is specified for and Rm (H1==0 and H2==0), the result is UNPREDICTABLE. So for the armv4 and armv5 I wouldnt try to make your 0x4408 instruction as it is unpredictable.

    The armv7-m doc does not say that so in theory okay for that architecture. dont know what the armv6m says.