Escolar Documentos
Profissional Documentos
Cultura Documentos
STMIA
STMIA r1,
r1,{r0,
{r0,r2,
r2,r4}
r4} ;;mem
mem3232[r1]
[r1]:=
:=r0r0
mem3232[r1 + 4]:=
;;mem [r1 + 4] :=r2
r2
;;mem
mem32 [r1 + 8] :=r4
[r1 + 8] := r4
32
So far, r1, the base address register, has not been changed. You
can update this pointer register by adding '!' after it:
LDMIA
LDMIA r1
r1!!, ,{r2-r9}
{r2-r9} ;;r2
r2:=
:=mem
mem3232[r1]
[r1]
;; .
.
;;r9
r9:=
:=mem
mem3232[r1+28]
[r1+28]
;;r1
r1 := r1++32
:= r1 32
load multiple
update r1
after used
meaning of LDMIA
instruction
I - increment A - base address is
base address incremented after it is
used load registers r2 to r9
ADR
ADR r0,
r0,src_addr
src_addr ;;initialize
initializesrc
srcaddr
addr
ADR
ADR r1, dest_addr
r1, dest_addr ;;initialize
initialize destaddr
dest addr
LDMIA
LDMIA r0!,
r0!,{r2-r9}
{r2-r9} ;;fetch
fetch88words
wordsfrom
frommem
mem
;; and update r0 :=r0
and update r0 := r0++32
32
STMIA
STMIA r1,
r1,{r2-r9}
{r2-r9} ;;copy
copy 8 words to mem,r1
8 words to mem, r1unchanged
unchanged
When using LDMIA and STMIA instructions, you:-
INCREMENT the address in memory to load/store your data
the increment of the address occurs AFTER the address is used.
In fact, one could use 4 different form of load/store:
Increment - After LDMIA and STMIA
Increment - Before LDMIB and STMIB
Decrement - After LDMDA and STMDA
Decrement - Before LDMDB and STMDB
higher
register
numbers
in higher
addresses
STMED
STMED r13!
r13!, ,{r1,
{r1,r3-r5,
r3-r5,r14}
r14} ;;push
pushr1,r3,r4,r5,r14
r1,r3,r4,r5,r14onto
ontostack
stack
;;stack
stack descending inmem
descending in mem
;;r13
r13points
pointsto
tonext
nextempty
emptyloc.
loc.
ARM does not have a POP instruction. In this case, we can use:
LDMIB
LDMIB r13!,
r13!,{r1,
{r1,r3-r5,
r3-r5,r14}
r14} ;;Pop
Popr1,
r1,r3-r5,
r3-r5,r14
r14from
fromstack
stack
Subroutines
main program
....
call ....
BL SUB1 ; call subroutine SUB1 return
ADD r0, r1, r2 ;
....
Nested Subroutines
Since the return address is held in register r14, you should not call
a further subroutine without first saving r14.
It is also a good software engineering practice that a subroutine
does not change any register values except when passing results
back to the calling program.
This is the principle of information hiding: try to hide what the
subroutine does from the calling program.
How do you achieve these two goals? Use a stack to:
Preserve r14
Save, then retrieve, the values of registers used inside
subroutine
BL
BL SUB1
SUB1
..
..
SUB1
SUB1 STMED
STMED r13!,
r13!,{r0-r2,
{r0-r2,r14}
r14} ;;push
pushwork
work&&link
linkregisters
registers
.
.
BL
BL SUB2
SUB2 ;;jump
jumpto
toaanested
nestedsubroutine
subroutine
LDMED
LDMED r13!,
r13!,{r0-r2,
{r0-r2,r14}
r14} ;;pop
popwork
work&&link
linkregisters
registers
MOV
MOV pc, r14
pc, r14 ;;return to calling program
return to calling program
on entry to SUB1 when return from SUB1
high
r13 r14 high r13' (r14)
r2 (r2)
SP moves
down r1 (r1)
r0 (r0)
r13' r13
low low
stack memory
SP when
inside SUB2