4

Strangely, I cannot find an explanation as to how str works in assembly language.

I understand that the following...

str r1,[r2]

...will store whatever is in register 1, r1, in the address of register 2, r2. However, I would like an explanation as to how str works when the square brackets are much more complicated. For example:

str r1,[r0,r3,lsl#2]

What is going on here? I want to know where the value of r1 will end up, and what will be its value. I can't test it, so I am going to take a guess as to what I think is going on.

r3 is logically shifted by 2. It is then added to r0. Finally, r1 is added to r0.

This is my guess, though even to me this does not sound correct. Can someone clarify this for me?

buydadip
  • 8,890
  • 22
  • 79
  • 154
  • Possible duplicate of [Understanding str in ARM](http://stackoverflow.com/questions/35186848/understanding-str-in-arm) – artless noise Feb 10 '16 at 13:50
  • 2
    why cant you find this it is well documented at arms website. did you even look at all? arms docs have nice pseudo code that explain how each instruction works. – old_timer Feb 10 '16 at 15:10

2 Answers2

7

str r1,[r0,r3,lsl#2]

What is going on here?

The instruction above basically says: r0 + (r3 << 2) = r1, or if we manually "expand" the bit-shift: r0 + (r3 * 4) = r1

The notation is <instruction> <src> [<dst>, <offset>, <shift>].

Note that offsets can also be negative (e.g. -r3, #lsl2).

I want to know where the value of r1 will end up, and what will be its value.

You need to know the actual values of r0 and r3 at a specific point in time during its execution before you can know any of this. This is like asking "What is the value of y in y = f(x) : x * 2?" without knowing anything about x.

r3 is logically shifted by 2. It is then added to r0.

Yes.

Finally, r1 is added to r0.

The datum in r1 is stored in (not added to) the location calculated by the left-hand side.

code_dredd
  • 5,915
  • 1
  • 25
  • 53
  • ARM can negate the index in an effective address? That's neat. x86 can't do that, only the `base+index*scale` part. What range, if any of immediate displacements are encodable in a load/store? – Peter Cordes Feb 10 '16 at 09:59
  • 1
    @PeterCordes: I found the range for the offset is `[-4095, +4095]`, not `[-4096, +4095]`. The reason given is that the "immediate offset is stored as a 12-bit magnitude plus one bit 'direction', not as a 13-bit two's complement number." [source](http://www.peter-cockerell.net/aalp/html/ch-3.html) – code_dredd Feb 10 '16 at 10:24
  • Ah, so it's `base + index*scale` OR `base + disp`, but not `base + i*s + disp`. That makes sense for a fixed insn-length ISA like ARM (vs. [x86's harder-to-decode insns that can do base+idx*scale + 8bit or 32bit signed displacement, with each of the components being optional](http://stackoverflow.com/a/34058400/224132)). The +/- bit is probably the same one that affects the index, so it kinda makes sense for it not to work as another bit of a 2's complement number. Thanks for the link; looks like a good rundown on the insn set. – Peter Cordes Feb 10 '16 at 11:15
4

r3 is logically shifted by 2. It is then added to r0. Finally, r1 is added to r0.

r1 isn't added to anything. It's stored at the address calculated by what you described in the first two sentences. I.e.:

[r0 + (r3 << 2)] = r1

See Load and Store Word or Unsigned Byte - Scaled register offset in the ARM Architecture Reference Manual for further information.

I want to know where the value of r1 will end up, and what will be its value.

If by the second part of that sentence you mean "I want to know what the value of r1 will be" then the answer is "That's impossible to say based on the given information". It will have whatever value that was last assigned to it.

Michael
  • 57,169
  • 9
  • 80
  • 125