|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
一、定义:栈(Stack)是限定仅在一端进行插入或删除操作的线性表。+ b& T' G2 f! h* J) m$ K0 D
因此,对栈来说,可以进行插入或删除操作的一端端称为栈顶(top),相应地,另一端称为栈底(bottom)。不含元素的空表称为空栈。由于堆栈只允许在一端进行操作,因而按照后进先出(LIFO-Last In First Out)的原理运作。从栈顶的定义来看,栈顶的位置是可变的。空栈时,栈顶和栈底重合;满栈时,栈顶离栈底最远。ARM为堆栈提供了硬件支持,它使用一个专门的寄存器(堆栈指针)指向堆栈的栈顶。而且7种模式都有各自独立的堆栈指针,也就是有各自独立的堆栈空间。6 v! v1 P0 \9 W3 m: G$ F
二、如何描述一个栈
5 [- Z- l8 D3 P& B准确描述一个栈的特点需要两个参数9 `+ N3 c$ j9 k4 ~& v2 @
栈地址的增长方向:ARM将向高地址增长(也叫做向上增长)的栈称为递增栈(ascendant Stack),将向低地址增长(也叫做向下增长)的栈称为递减栈(descendantStack)/ N ]' @+ ]* M/ `$ c; y6 ` z
栈指针的指向位置:ARM将栈指针指向栈顶元素位置的栈称为满栈(Full Stack),讲栈指针指向即将入栈的元素位置的栈称为空栈(Empty Stack)+ T8 P. a4 [7 h: Y7 i8 L
根据栈地址增长方向雨栈指针指向位置的不同,自然可以将栈分为四类:* M* U8 D& J+ n! V5 i( t
U) H( K! `& ?6 l" j( N/ r( s
下图描述了四种不同类型的栈,其中虚线部分表示即将入栈的元素。4 I; N; I. G2 ^+ h# ^
7 ^3 f2 A/ g$ I; j' I* P1 x三、栈指令
2 h0 s) {2 J5 L: b/ i6 |1 ]4 k栈的操作指令无非两种:入栈和出栈,由于ARM描述了四种不同类型的栈,因此对应的栈指令一共有8条。 % b; d4 @. P7 g, \# { n1 o
STM:(STore Multiple data)表示存储数据,即入栈。
8 m: f9 L, |" |. e; A, j! ^' R! vLDM:(LoaD Multiple data)表示加载数据,即出栈。
! p. K6 C1 ]. r) x一般情况下,可以将栈操作指令分解为两步微指令:数据存取和栈指针移动。这两步操作的先后顺序和栈指针的移动方式由栈的类型决定。, g$ S9 r+ i ?
- k& W$ ?/ B6 T( M1 J0 \! u- ?9 A
ARM中存在一组缓冲区操作指令和栈指令是一一对应的,他们完成相同的功能。这些指令含义的区别来源于对存取操作的缓冲区指针地址增长方向,以及存取操作和缓冲区指针移动的先后顺序决定的。这个和前面描述的栈类型的分类原则十分相似。
1 a. v# u7 Q( O" ^/ X2 \+ q1 ] o1 k! X, N8 w, ^+ u
四、实例+ {$ k8 p3 M' e0 [! j
虽然ARM的栈类型和相关的操作指令比较繁琐,但是实际上最常用的还是和x86指令集相同的栈类型:栈向低地址方向增长,且栈指针指向栈顶元素的位置,即ARM的FD栈。因此最常见的ARM栈指令操作是STMFD和LDMFD。, ?' S1 Q4 W4 d
例如入栈指令:
" P# M% m9 ?+ Z- Y' fSTMFD SP,{R0-R3}
0 M2 p9 z9 t6 R* H7 Q1 f5 t实际的微指令操作为:
6 D0 O c/ Z! L- T3 N[SP-4] <= R3. _; \! B% M# q
[SP-8] <= R2
* u/ v' }" b2 O5 J$ w) c6 b9 H, Q[SP-12] <= R1
, g8 ?, q8 O1 s7 y+ \[SP-16] <= R0. K- ~: l/ d! b/ {! ]. m- S. i8 l
在ARM的指令系统中,递减栈入栈操作的参数入栈顺序是从右到左依次入栈,而参数的出栈顺序则是从左到右的逆操作。对于递增栈,相应的操作则全部取反。
7 i* [. y0 s) T2 b: l例如出栈指令:- }! _+ ^& v& L8 W$ T$ w& Z
LDMFD SP,{R4-R7}
, d- Z4 l4 q! A8 w% p3 c实际的微指令操作为:$ l: H' x' n% y" p2 O& |
[SP] => R4
' u) d( P, N! }, m, v2 q7 v[SP+4] => R5% w5 d" I/ O9 W
[SP+8] => R6
+ P% h: c* K% Q* `! k[SP+12] => R7( |3 `) b, G( Y: r% m2 Y2 T
上述的入栈和出栈指令其实仅仅对栈做了存取操作,并未真正改变SP指针的值。正常情况下,我们希望对栈操作后能自动修改栈指针SP的值,使用如下指令可以达到该目的。/ t& ~0 T& u4 @) f+ A: F& |+ f
STMFD SP!,{R0-R3}% i" a7 j6 {, V: e6 j
对应的微指令操作为:* v$ S7 Y% e2 h
[SP-4] <= R3
2 n' W- E/ s v* O- v6 b. s7 X[SP-8] <= R2$ R' I# J* A# B c% v: Z
[SP-12] <= R1
. i8 x& U% |% ?. f+ S7 o; B[SP-16] <= R06 R& k N( P3 H
SP = SP - 16# s2 P( J) K' v% l
同样的:
- ?( J; V! d2 q9 v [$ {' yLDMFD SP!,{R4-R7}; K s( d$ M$ N& J% c
对应的微指令操作为:) S: b5 E! H9 r5 e, z
[SP] => R4
5 H" c _0 K$ |+ |+ i1 b[SP+4] => R5$ i. b6 Z4 a- Q1 A- N& p: i! q6 V
[SP+8] => R6/ j* U- b' e' k
[SP+12] => R7
3 r* a% ]' U) C: C5 v3 r$ eSP = SP + 16. [& u( n$ _0 p0 T0 j0 P( f
# J" y U+ P2 V9 ]' w
2 a7 Y& u# E3 C7 D: e% |( v% M |
|