|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
一、定义:栈(Stack)是限定仅在一端进行插入或删除操作的线性表。7 c4 _ ~) j7 n( }) t& Q; b
因此,对栈来说,可以进行插入或删除操作的一端端称为栈顶(top),相应地,另一端称为栈底(bottom)。不含元素的空表称为空栈。由于堆栈只允许在一端进行操作,因而按照后进先出(LIFO-Last In First Out)的原理运作。从栈顶的定义来看,栈顶的位置是可变的。空栈时,栈顶和栈底重合;满栈时,栈顶离栈底最远。ARM为堆栈提供了硬件支持,它使用一个专门的寄存器(堆栈指针)指向堆栈的栈顶。而且7种模式都有各自独立的堆栈指针,也就是有各自独立的堆栈空间。8 f+ L2 l6 _8 E& P) q" j7 ^: V
二、如何描述一个栈
& I; c/ y/ y/ R# _, O% S准确描述一个栈的特点需要两个参数+ S/ z' j- j$ E0 |* Y l( `5 z
栈地址的增长方向:ARM将向高地址增长(也叫做向上增长)的栈称为递增栈(ascendant Stack),将向低地址增长(也叫做向下增长)的栈称为递减栈(descendantStack)
0 x: `3 [4 K1 Z, Z# P. k栈指针的指向位置:ARM将栈指针指向栈顶元素位置的栈称为满栈(Full Stack),讲栈指针指向即将入栈的元素位置的栈称为空栈(Empty Stack)) ?6 L1 Z+ E5 Y1 Z( m, X
根据栈地址增长方向雨栈指针指向位置的不同,自然可以将栈分为四类:& S4 q: n) g9 b! e( M$ r
$ F S# e0 o, }; A4 | l下图描述了四种不同类型的栈,其中虚线部分表示即将入栈的元素。
1 V5 Z3 N+ G" W( v* v
+ l9 ]; y$ k) H5 t- d三、栈指令0 A4 F# S0 X7 L7 B, j; P! ~! N$ L, x/ y
栈的操作指令无非两种:入栈和出栈,由于ARM描述了四种不同类型的栈,因此对应的栈指令一共有8条。 % \7 K. s5 A# I9 T1 w
STM:(STore Multiple data)表示存储数据,即入栈。' \% H: G+ Q! Q! L- a
LDM:(LoaD Multiple data)表示加载数据,即出栈。
' k) {; a, z6 \9 }% K( k一般情况下,可以将栈操作指令分解为两步微指令:数据存取和栈指针移动。这两步操作的先后顺序和栈指针的移动方式由栈的类型决定。
' ?$ U5 m! O# N2 X$ ^$ u3 V- I4 u: z# M5 u, a% Q
ARM中存在一组缓冲区操作指令和栈指令是一一对应的,他们完成相同的功能。这些指令含义的区别来源于对存取操作的缓冲区指针地址增长方向,以及存取操作和缓冲区指针移动的先后顺序决定的。这个和前面描述的栈类型的分类原则十分相似。
- g4 K! Q0 s! H5 a0 m, H
p6 r' r' q6 w; F四、实例
4 F# ^' c* ?- l/ y3 l虽然ARM的栈类型和相关的操作指令比较繁琐,但是实际上最常用的还是和x86指令集相同的栈类型:栈向低地址方向增长,且栈指针指向栈顶元素的位置,即ARM的FD栈。因此最常见的ARM栈指令操作是STMFD和LDMFD。/ V! ]' o& }# g8 i
例如入栈指令:
# j* ^& ?; D: X" N1 QSTMFD SP,{R0-R3}2 I1 \- R- z+ x, {
实际的微指令操作为:
) Z$ C' w8 W2 j0 K[SP-4] <= R3' |& [, Z; B/ v* a! q! J
[SP-8] <= R27 ^% t( u9 J0 w4 L3 B- z: f
[SP-12] <= R1
6 Q' K& h( G8 ^7 e8 w+ Z; U8 b[SP-16] <= R0
' D' T$ H, g, J5 m在ARM的指令系统中,递减栈入栈操作的参数入栈顺序是从右到左依次入栈,而参数的出栈顺序则是从左到右的逆操作。对于递增栈,相应的操作则全部取反。 2 u, |: s& t! _4 g/ E1 T+ e
例如出栈指令:: y/ c* ^( p8 p6 G+ Y3 N& q
LDMFD SP,{R4-R7}3 m: |+ I" C7 a! O9 }' H- r
实际的微指令操作为:& f+ z& k9 J: F7 R
[SP] => R4" l7 W+ ^. I% P" f- A" x8 Z
[SP+4] => R5( x P7 t* ]* O
[SP+8] => R6
( _% b' V6 F/ n/ u; Q' C1 b/ v) p ^[SP+12] => R7
: R- ]6 h8 H" B* _+ b9 Q: A上述的入栈和出栈指令其实仅仅对栈做了存取操作,并未真正改变SP指针的值。正常情况下,我们希望对栈操作后能自动修改栈指针SP的值,使用如下指令可以达到该目的。
, _4 c( R# X" j x8 Z) `STMFD SP!,{R0-R3}4 ]/ X ~8 `. V. U8 M& Y" j
对应的微指令操作为:+ P, L" a6 B3 J0 ]4 b3 E
[SP-4] <= R3
6 _& U# _3 I2 G& x/ B[SP-8] <= R24 g, s) `/ l# E
[SP-12] <= R1
. k8 W% }$ r. }% z( [8 w[SP-16] <= R0
0 ~. r* b$ K) @' O4 u1 kSP = SP - 16( y& H K$ \$ y, l4 T
同样的:
+ Q p8 m% Q: j- C) V6 V3 ELDMFD SP!,{R4-R7}' H/ u& [- `! A7 o
对应的微指令操作为:' B/ |/ q N' j! _' w! d0 E, W
[SP] => R4( M3 F# i( o! v/ u5 G# e* F
[SP+4] => R5
/ A" d& C& r% z6 B# h[SP+8] => R6
4 k4 u/ G* n4 o" S/ T$ T1 W[SP+12] => R7
& T/ p: N6 r" {SP = SP + 16
, a8 ?2 y* P# h$ a* S5 v4 L7 M7 {, h1 [, d' B* z6 h1 Z* I I1 o, t2 r
! ]* J& ~0 J( b1 }7 z |
|