Skip to main content
oys_mo
Associate II
December 13, 2010
Question

Question regarding ARM assembler's LDR instruction and address rounding

  • December 13, 2010
  • 13 replies
  • 3748 views
Posted on December 13, 2010 at 05:12

Question regarding ARM assembler's LDR instruction and address rounding

    This topic has been closed for replies.

    13 replies

    oys_mo
    oys_moAuthor
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:18

    Also - a separate, but related question - the same page says that in the case of LDR

    ''The loaded data is rotated right by one, two or three bytes according to bits [1:0] of the address.''

    What's up with that?

    EDIT: Okay, look at this:

    Say we got the same exact program as above, except there is a

    .byte 0x77

    in the .data segment, just before the .word - giving us the following in memory (accounting for endianness):

    77 BE BA FE CA

    Assume that the 77-byte is word aligned. Now, the address of var1 surely will be the same as before + 1. If we follow what the page I linked to said, we would now round this address down so that we read the 4 bytes

    77 BE BA FE

    Note that I am talking about the first LDR here, I have not mixed in offsets yet.

    Now the page says that we ought to rotate this right, a set amount of bytes according to the two least significant bits. Since the address we requested (the BE byte) is word aligned + 1, we know that its two least significant bits must be 10 (little endian). So we are going to rotate our data 1 byte to the right. Doing this, accounting for endianness, I get

    BE BA FE 77

    And as the page said,

    ''For a little-endian memory system, this causes the addressed byte to occupy the least significant byte of the register.''

    But that is not what my debugger tells me. I get a nice 0xFEBABE77 in my register. So it seems like there has been no rotation... I am thoroughly confused.
    oys_mo
    oys_moAuthor
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:18

    Hmm according to the docs on keils website unaligned access is available - and on by default - on ARMv7. I use GNU's assembler, though, so there might be differences. Guess I'll just keep my data aligned. 

    Tesla DeLorean
    Guru
    May 17, 2011
    Posted on May 17, 2011 at 14:18

    Unaligned memory accesses will typically cause the processor to fault in most ARM implementations.

    So you shouldn't do 32-bit or 16-bit access from ODD addresses. And 32-bit access should have (A0=A1=0)

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    oys_mo
    oys_moAuthor
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:18

    I was in privileged mode, and it kind of worked, it just gave me slightly unexpected results...

    It's not that I'm going to use unaligned memory access, I was just testing it :) Knowledge is power, as they say.

    damh
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 14:18

    In startup mode the mcus (STM32F103xx) support unaligned memory accesses, BUT they use much more cycles than aligned accesses (about factor 3-6). Accesses to flash can have higher factors because of waitstates!

    In normal user mode unaligned access can fault. I think this can be disabled but with the same costs!

    stforum2
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 14:18

    Section A6.7.42 shows the encodings for LDR (immediate).

    What code bytes is your assembler generating?

    oys_mo
    oys_moAuthor
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:18

    Are you sure? The document you mentioned didn't say anything about rounding at all, not that I could find at least. Still, it's a useful resource.

    stforum2
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 14:18

    Cortex-M3 LDR is different to ARM7 LDR.  There is no rotation on Cortex-M3.

    For Cortex-M3 alignment behaviour see document ARM DDI 0405B section A3.2.

    (Maybe there is a later edition of this document).

    oys_mo
    oys_moAuthor
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:18

    The LDR R1,[R0] was unexpected, as I thought it should rotate, but if you are right, I guess it is behaving normally.

    There is nothing unexpected in my original code, as long as one applies the address offset after rounding, which I suppose one does?

    .syntax unified .cpu cortex-m3 .fpu softvfp .thumb .section .data .align 2 var1: .word 0xCAFEBABE @ An initialized word in the .data segment, word aligned .section .text .global main .thumb_func main: ldr r0, =var1 ldr r1, [r0] @ r1 now contains 0xCAFEBABE ldr r1, [r0, #3] @ r1 now contains 0xFFFFFFCA bx lr

    assembles to

    00 00 00 00 00 00 00 00 5F F8 E0 F1 02 48 01 68 D0 F8 03 10 70 47 00 00 00 00 00 20 00 F0 26 F8 0C 48 80 F3 08 88 00 21 03 E0 0B 4B 5B 58 43 50 04 31 0A 48 0A 4B 42 18 9A 42 F6 D3 09 4A 02 E0 00 23 42 F8 04 3B 08 4B 9A 42 F9 D3 FF F7 DE FF 70 47 00 00 00 80 00 20 48 02 00 08 00 00 00 20 04 00 00 20 04 00 00 20 04 00 00 20 70 47 FE E7 BE BA FE CA FF FF FF FF FF FF FF FF FF FF FF FF

    where

    ldr r0, =var1 becomes ldr r0, [PC, #8] @ code 0x0248 ldr r1, [r0] stays the same @ code 0x0168 ldr r1, [r0, #3] becomes ldr.w r1, [r0, #3] @ code 0xD0F80310

    According to my debugger.
    oys_mo
    oys_moAuthor
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:18

    Hm my version of the document did not even have an A6 7.42 section :S Could you quote the text?

    The following code  

    .syntax unified .cpu cortex-m3 .fpu softvfp .thumb .section .data .align 4 .byte 0x77 var1: .word 0xCAFEBABE @ Memory layout: @ 2000.0000: 77 BE BA FE CA 00 00 00 .section .text .global main .thumb_func main: ldr r0, =var1 @ r0 contains 0x20000001 ldr r1, [r0] @ r1 contains 0xFEBABE77 bx lr

    seems to assemble into

    00 00 00 00 00 00 00 00 5F F8 E0 F1 01 48 01 68 70 47 00 00 01 00 00 20 00 F0 26 F8 0C 48 80 F3 08 88 00 21 03 E0 0B 4B 5B 58 43 50 04 31 0A 48 0A 4B 42 18 9A 42 F6 D3 09 4A 02 E0 00 23 42 F8 04 3B 08 4B 9A 42 F9 D3 FF F7 E0 FF 70 47 00 00 00 80 00 20 44 02 00 08 00 00 00 20 10 00 00 20 10 00 00 20 10 00 00 20 70 47 FE E7 77 BE BA FE CA 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF

    if I'm thinking correctly here. So the first LDR seems to assemble into a 0x0148 (ADR?), and the second to a 0x0168.