1、棧:FILO先進后出的數據結構
棧底是第一個進棧的數據的位置(壓箱?底)?
棧頂是最后一個進棧的數據位置
2、根據SP指針指向的位置,棧可分為?滿棧和空棧?
滿棧:當sp指針總是指向最后壓入堆棧?的數據(ARM采用滿棧)
空棧:當堆棧指針SP總是指向下一個將?要放入數據的空位置。
3、根據SP指針移動的方向,可分為升?棧和降棧?
升棧:隨數據的入棧,SP由低地址-->?高地址?
降棧:隨數據的入棧,SP由高地址-->?低地址(ARM采用降棧)
4、棧幀:存儲在用戶棧上的(當然內核棧同樣適用)每一次函數調用涉及的相關信息的記錄單元 ;?棧幀(stack frame)就是一個函數所使用的那部分棧,所有函數的棧幀串起來就組成了一個完整的棧。
棧幀的兩個邊界分別有FP(R11)和SP(R13)L來限定。?
棧幀
棧的作用:
1)保存局部變量
分析代碼:
[html]?view plain?copy
#include?
int?main()
{
int?a;
a++;
return?a;
}
反匯編之后的代碼;
[html]?view plain?copy
stack:?file?format?elf32-littlearm
Disassembly?of?section?.text:
00000000?:
#include?
int?main()
{
0:?e52db004?push?{fp}?;?(str?fp,?[sp,?#-4]!)?@將棧幀底部指針FP壓入棧中;創建屬于main函數的棧幀。
4:?e28db000?addfp,?sp,?#0;?0x0?@fp指針為函數棧幀的底部,
8:?e24dd00c?subsp,?sp,?#12?;?0xc?@sp指針為棧幀的頂部,同時為棧的棧頂。
int?a;
a++;
c:?e51b3008?ldrr3,?[fp,?#-8]?@由此三句可知變量a在棧幀中執行了加法操作,及棧幀具有保存局部變量的作用
10:?e2833001?addr3,?r3,?#1;?0x1
14:?e50b3008?strr3,?[fp,?#-8]
return?a;
18:?e51b3008?ldrr3,?[fp,?#-8]
}
2)保存函數的參數?
分析代碼:
[html]?view plain?copy
#include?
void?func1(int?a,int?b,int?c,int?d,int?e,int?f)
{
int?k;
k=e+f;
}
int?main()
{
func1(1,2,3,4,5,6);
return?0;
}
反匯編之后的代碼;
void?func1(int?a,int?b,int?c,int?d,int?e,int?f)?@多于4個參數
{
0:?e52db004?push?{fp}?;?(str?fp,?[sp,?#-4]!)@保存main函數的棧幀底部指針FP
4:?e28db000?addfp,?sp,?#0;?0x0
8:?e24dd01c?subsp,?sp,?#28?;?0x1c?@由棧幀頂部指針SP創建一片棧幀保存子函數的前四個參數
c:?e50b0010?strr0,?[fp,?#-16]@?a
10:?e50b1014?strr1,?[fp,?#-20]@?b
14:?e50b2025?strr2,?[fp,?#-24]@?c
18:?e50b301c?strr3,?[fp,?#-28]@?d
int?k;
k=e+f;
1c:?e59b3004?ldrr3,?[fp,?#4]@在子函數的棧幀中實現第五個參數與第六個參數的運算
20:?e59b2008?ldrr2,?[fp,?#8]?@由ldrr2,?[fp,?#8]知參數保存在main函數的棧幀中,并運算
24:?e0833002?addr3,?r3,?r2?@以子函數的棧幀底部指針(fp)做參考坐標實現對參數的查找
28:?e50b3008?strr3,?[fp,?#-8]
}
2c:?e28bd000?addsp,?fp,?#0;?0x0

30:?e8bd0800?pop{fp}
34:?e12fff1e?bx?lr
00000038?:
int?main()
{
38:?e92d4800?push?{fp,?lr}@由于調用子函數,先保存main函數的棧幀底部指針FP和返回地址LR(當前PC指針的下一地址)
3c:?e28db004?addfp,?sp,?#4;?0x4?@可知先壓入FP,后壓入lr.把此時子函數(被調用者)的棧幀底部指針FP指向保存在子函數棧幀的main函數(調用者)的棧幀底部指針FP
40:?e24dd008?subsp,?sp,?#8;?0x8?@創建棧
func1(1,2,3,4,5,6);
44:?e3a03005?movr3,?#5;?0x5
48:?e58d3000?strr3,?[sp]
4c:?e3a03006?movr3,?#6;?0x6
50:?e58d3004?strr3,?[sp,?#4]
54:?e3a00001?movr0,?#1;?0x1?@用通用寄存器保存前四個參數的值
58:?e3a01002?movr1,?#2;?0x2
5c:?e3a02003?movr2,?#3;?0x3
60:?e3a03004?movr3,?#4;?0x4
64:?ebfffffe?bl?0?
return?0;
68:?e3a03000?movr3,?#0;?0x0
}
6c:?e1a00003?movr0,?r3
70:?e24bd004?subsp,?fp,?#4;?0x4
74:?e8bd4800?pop{fp,?lr}
78:?e12fff1e?bx?lr
注:C中,若函數的參數小于等于4個,則用通用寄存器保存其參數值,多于4個的參數保存在棧中
3)保存寄存器的值
分析代碼:
[html]?view plain?copy
include?
void?func2(int?a,int?b)
{
int?k;
k=a+b;
}
void?func1(int?a,int?b)
{
int?c;
func2(3,4);
c=a+b;
}
int?main()
{
func1(1,2);
return?0;
}
反匯編之后的代碼;
[html]?view plain?copy
void?func2(int?a,int?b)
{
0:?e52db004?push?{fp}?;?(str?fp,?[sp,?#-4]!)
4:?e28db000?addfp,?sp,?#0;?0x0
8:?e24dd014?subsp,?sp,?#20?;?0x14
c:?e50b0010?strr0,?[fp,?#-16]?@保存寄存器的值
10:?e50b1014?strr1,?[fp,?#-20]
int?k;
k=a+b;
14:?e51b3010?ldrr3,?[fp,?#-16]
18:?e51b2025?ldrr2,?[fp,?#-20]
1c:?e0833002?addr3,?r3,?r2
20:?e50b3008?strr3,?[fp,?#-8]
}
24:?e28bd000?addsp,?fp,?#0;?0x0
28:?e8bd0800?pop{fp}
2c:?e12fff1e?bx?lr
00000030?:
void?func1(int?a,int?b)
{
30:?e92d4800?push?{fp,?lr}
34:?e28db004?addfp,?sp,?#4;?0x4
38:?e24dd010?subsp,?sp,?#16?;?0x10
3c:?e50b0010?strr0,?[fp,?#-16]?@代碼44行調用func2函數后,又使用r0\r1保存參數,所以此時將r0\r1寄存器的
40:?e50b1014?strr1,?[fp,?#-20]@值放入棧中
int?c;
func2(3,4);
44:?e3a00003?movr0,?#3;?0x3
48:?e3a01004?movr1,?#4;?0x4
4c:?ebfffffe?bl?0?
c=a+b;
50:?e51b3010?ldrr3,?[fp,?#-16]
54:?e51b2025?ldrr2,?[fp,?#-20]
58:?e0833002?addr3,?r3,?r2
5c:?e50b3008?strr3,?[fp,?#-8]
}
60:?e24bd004?subsp,?fp,?#4;?0x4
64:?e8bd4800?pop{fp,?lr}
68:?e12fff1e?bx?lr
0000006c?:
int?main()
{
6c:?e92d4800?push?{fp,?lr}
70:?e28db004?addfp,?sp,?#4;?0x4
func1(1,2);
74:?e3a00001?movr0,?#1;?0x1
78:?e3a01002?movr1,?#2;?0x2
7c:?ebfffffe?bl?30?
return?0;
80:?e3a03000?movr3,?#0;?0x0
}
84:?e1a00003?movr0,?r3
88:?e24bd004?subsp,?fp,?#4;?0x4
8c:?e8bd4800?pop{fp,?lr}
90:?e12fff1e?bx?lr
初始化棧:即對SP指針賦予一個內存地址(統一標準:2440、6410、210)
在內存的64MB位置即ldr sp, =0x34000000(2440)
ldr sp, =0x54000000(6410)
ldr sp, =0x24000000(210)
由上可知ARM采用滿棧(指向剛入棧的數據)、降棧(由高地址向低地址入棧)
問題:因為ARM不同工作模式有不同的棧,定義棧的技巧是什么,避免定義相同的地址使用不同棧?
轉自:http://blog.csdn.net/u011467781/article/details/39559737
棧的最主要特點是后進先出。
棧是一種運算受限的線性表,限定僅在表尾進行插入和刪除操作的線性表。棧的所有插入和刪除操作均在棧頂進行,而棧底不允許插入和刪除。
向一個棧插入新元素又稱作進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;從一個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素。
擴展資料:
棧作為一種數據結構,是一種只能在一端進行插入和刪除操作的特殊線性表。它按照先進后出的原則存儲數據,先進入的數據被壓入棧底,最后的數據在棧頂。
1、進棧(PUSH)算法
①若TOP≥n時,則給出溢出信息,作出錯處理(進棧前首先檢查棧是否已滿,滿則溢出;不滿則作②);
②置TOP=TOP+1(棧指針加1,指向進棧地址);
③S(TOP)=X,結束(X為新進棧的元素);
2、退棧(POP)算法
①若TOP≤0,則給出下溢信息,作出錯處理(退棧前先檢查是否已為空棧, 空則下溢;不空則作②);
②X=S(TOP),(退棧后的元素賦給X):
③TOP=TOP-1,結束(棧指針減1,指向棧頂)。
鵬仔微信 15129739599 鵬仔QQ344225443 鵬仔前端 pjxi.com 共享博客 sharedbk.com
免責聲明:我們致力于保護作者版權,注重分享,當前被刊用文章因無法核實真實出處,未能及時與作者取得聯系,或有版權異議的,請聯系管理員,我們會立即處理! 部分文章是來自自研大數據AI進行生成,內容摘自(百度百科,百度知道,頭條百科,中國民法典,刑法,牛津詞典,新華詞典,漢語詞典,國家院校,科普平臺)等數據,內容僅供學習參考,不準確地方聯系刪除處理!郵箱:344225443@qq.com)
圖片聲明:本站部分配圖來自網絡。本站只作為美觀性配圖使用,無任何非法侵犯第三方意圖,一切解釋權歸圖片著作權方,本站不承擔任何責任。如有惡意碰瓷者,必當奉陪到底嚴懲不貸!