assemblycortex-mthumb

Writing data to absolute address


I'm currently playing around a bit with assembler on a Cortex-M3 microcontroller. I'm not sure if this is important, but here you go.

I need to write a value into to a certain address in memory. Here is what I tried:

LDR     R4, =__cs3_interrupt_vector_cortex_m
STR     R4, [=VTOR]

But it seems like I need to reference the VTOR address relative to the PC register. The question is if there is a way to not reference the address relativ and let this do automatically (so that it would basically look like my approach).

I'm using GNU Assembler.


Solution

  • You need to load the destination address to a register. I assume that VTOR is a memory address or 'C' pointer and __cs3_interrupt_vector_cortex_m is a constant. Ie, you wish to write a 32bit constant to an address. If this is the case then,

     ; Get value __cs3_interrupt_vector_cortex_m to r4
     ldr r4, =__cs3_interrupt_vector_cortex_m 
     ldr r5, =VTOR ; address 'VTOR' to r5.
     str r4, [r5]  ; write the constant to 'VTOR' address.
    

    The ARM/Thumb/Thumb2 is a load-store architecture. You can not use memory operands in the load and store instructions. This simplifies the CPU design, but is different from M68K and x86 assembler.

    The syntax ldr rX, =val is explained in the Gnu assembler info pages. Generally it will convert to the following,

    ldr   rX, [pc, #offset]
    ...
    offset: .word val ; your constant is stored here.
    

    The pseudo-op .ltorg tells the assembler to dump the literal table; the offset portion of code above. You can add an .ltorg anywhere between sub-routines, etc.

    You can not use the syntax str r4,[=VTOR] as the equals syntax is only a short-cut for use with ldr. For example,

    ldr   rX,=7          ; is really 'mov rx,#7' in all modes.
    ldr   rX,=0xff       ; is 'mov rx,#0xff' for ARM and '[pc,#offset]' for thumb.
    ldr   rx,=0x12345678 ; will use the [pc, #offset] for all modes.
    

    You can use the ldr rX,=VTOR syntax to get the address to a register. It then takes another instruction like str rY, [rX] to actually write to that address.

    Constants are encoded inside an instruction so the constant range is very limited especially in thumb mode. I guess you are using thumb2 which may have more range.