FRIHOST FORUMS SEARCH FAQ TOS BLOGS COMPETITIONS
You are invited to Log in or Register a free Frihost Account!


Programming in ARM architecture





NewGuyinTown
I have some questions about the stacks used in ARM...

1.) STR Rx, [SP,#-4]!
2.) LDR Rx, [SP], #4

OK... I know the first instruction stores Rx into the stack. I also know that the SP will move 4 bit lower. I do not know if it's afterwards or before... what's that "!" mean?

For the second instructions, I know that the 4bit value will be popped into Rx. I also do know if it move the SP 4 bit higher afterwards or before the operation is performed.

Is there something special putting the #4 inside and outside of the []?

Thank you.
Kaneda
NewGuyinTown wrote:
I have some questions about the stacks used in ARM...

1.) STR Rx, [SP,#-4]!
2.) LDR Rx, [SP], #4

OK... I know the first instruction stores Rx into the stack. I also know that the SP will move 4 bit lower. I do not know if it's afterwards or before... what's that "!" mean?

For the second instructions, I know that the 4bit value will be popped into Rx. I also do know if it move the SP 4 bit higher afterwards or before the operation is performed.

Is there something special putting the #4 inside and outside of the []?

Thank you.


The "!" after the STore Register instruction indicates that the new memory address will be stored back into the SP register when done. I.e., it will store the value of Rx into the offset pointed to by SP - 4, then store SP - 4 into SP. Without the "!", SP wouldn't change to reflect the new stack offset.

Code:
STR/LDR Rx, [Rbase, #index] - store/load Rx into/from [Rbase + #index].
STR/LDR Rx, [Rbase, #index]! - store/load Rx into/from [Rbase + #index]. Write [Rbase + #index] into Rx.


The difference with:
Code:
STR/LDR Rx, [Rbase], #index


... is when the offset change will take place. When both the last two operands are inside square brackets, it's called "pre-indexed addressing". When the index is outside the square brackets, it's called "post-indexed addressing".

In "pre-indexed addressing", index is added to Rbase, and then Rx is stored into the resulting address. In "post-indexed addressing", Rx is stored into the address pointed to by Rbase, then index is added to Rbase.

This is somewhat like (but, of course, not the same as), in C:

Code:
int x = 3;
int y = x++; (assign x to y, then increment x by 1)
int y = ++x; (increment x by 1, then assign x to y)


So, you have four versions of the same call:

Code:
1. STR Rx, [SP,#-4]
2. STR Rx, [SP,#-4]!
3. STR Rx, [SP],#-4  ; NOTE! This is a hypothetical operation without the implied "!". Looks the same as (4), but our "intention" is different.
4. STR Rx, [SP],#-4  ; NOTE! This has an implied "!". We don't write it. This is how it actually works.


In (1), Rx will be stored into SP-4. SP will continue to point at the same address. (equivalent to x86: MOV eax, [esp-4])
In (2), Rx will be stored into SP-4. Then SP will point to [SP-4].
In (3), Rx will be stored into SP. SP will continue to point at the same address.
In (4), Rx will be stored into SP. Then SP will point to [SP-4].

As you can see, version (3) is useless. The #-4 index is never used. So, there's only three actual operations, "pre-indexed addressing without write-back" (1), "pre-indexed addressing with write-back" (2) and "post-indexed addressing (with write-back)" (4). For ease of writing, we leave the "!" out in "post-index addressing (with write-back)", because it makes no sense to have one without write-back.

Long story short, a breakdown:

STR Rx, [SP,#-4]!

STR - STore Register - you shouldn't really think of this as PUSH, because it works for any register (and the SP register doesn't really have to be the stack pointer, it's a general purpose register which may be used by an OS as a stack pointer). It's more similar to MOV with some extra features.

Rx - The register to store (R0-R14)

[SP,#-4] - Pre-indexed addressing. The address to store at:

SP - The stack pointer register (= R13)

#-4 - The offset

! - Write-back (i.e., store SP-4 into SP)

So, we store Rx into [SP-4], and decrement SP by 4.

LDR Rx, [SP], #4

LDR - LoaD Register - in the same way as above, not a dedicated POP.

Rx - The register to load into (R0-R14)

[SP], #4 - Post-indexed addressing:

SP - The stack pointer register (= R13). In this case holds the address to load from.

#4 - The offset

So, we load the value at [SP] into Rx, then increment SP by 4.

And in very short:

Your first operation moves SP to 4 bytes lower before the storing takes place. The second moves it to 4 bytes higher after the loading takes place. The "!" tells the CPU to write the new position back into SP. An "!" is implied after the second operation - it's an error to put one there.
Related topics
Java
How To : Improve Your PHP Programming
Learn Assembly: the LUCID way
Java Programming Introductory
Laws of Computer Programming
Programming Help & Support Guidelines
Programming
Microsoft plans to build more Unix features into future vers
Architecture
Programming links, info, and tutorials
xcode programming
The Secret Source of Google's Power
A wonderful place to learn CGI-programming
ARM microprocessor (programming in ARM)
Reply to topic    Frihost Forum Index -> Scripting -> Others

FRIHOST HOME | FAQ | TOS | ABOUT US | CONTACT US | SITE MAP
© 2005-2011 Frihost, forums powered by phpBB.