也谈栈和栈帧(三)
這次講ARM的棧幀布局和操作方法。
1.? ARM的棧幀
??? 先來看看ARM的棧幀布局圖:
????
??? 上圖描述的是ARM的棧幀布局方式,main stack frame為調(diào)用函數(shù)的棧幀,func1 stack frame為當(dāng)前函數(shù)(被調(diào)用者)的棧幀,棧底在高地址,棧向下增長。圖中FP就是棧基址,它指向函數(shù)的棧幀起始地址;SP則是函數(shù)的棧指針,它指向棧頂?shù)奈恢谩?span style="color:#0000f0;">ARM壓棧的順序很是規(guī)矩(也比較容易被黑客攻破么),依次為當(dāng)前函數(shù)指針PC、返回指針LR、棧指針SP、棧基址FP、傳入?yún)?shù)個數(shù)及指針、本地變量和臨時變量。如果函數(shù)準(zhǔn)備調(diào)用另一個函數(shù),跳轉(zhuǎn)之前臨時變量區(qū)先要保存另一個函數(shù)的參數(shù)。
??? ARM也可以用棧基址和棧指針明確標(biāo)示棧幀的位置,棧指針SP一直移動,相比于x86,ARM更為鮮明的特點是,兩個棧空間內(nèi)的地址(SP+FP)前面,必然有兩個代碼地址(PC+LR)明確標(biāo)示著調(diào)用函數(shù)位置內(nèi)的某個地址。 ? 2.? ARM的匯編指令和棧操作
??? ARM微處理器共有37個寄存器,其中31個為通用寄存器,6個為狀態(tài)寄存器。但是這些寄存器不能被同時訪問,具體哪些寄存器是可編程訪問的,取決于微處理器的工作狀態(tài)及具體的運行模式。但在任何時候,通用寄存器R0~R15、一個或兩個狀態(tài)寄存器都是可訪問的。有三個特殊的通用寄存器:
? 寄存器R13:在ARM指令中常用作堆棧指針SP
? 寄存器R14:也稱作子程序連接寄存器(Subroutine Link Register)即連接寄存器LR
? 寄存器R15:也稱作程序計數(shù)器PC
??? ARM進(jìn)行函數(shù)內(nèi)壓棧和出棧往往使用如下的語句:
??stmfd sp!, {r0-r9, lr}??? ;?滿遞減入棧,給寄存器r0-r9,lr壓棧,sp不斷減4
??ldmfd sp!, {r0-r9, pc}??? ; 滿遞減出棧,給寄存器r0-r9出棧,并使程序跳轉(zhuǎn)回函數(shù)的調(diào)用點,sp不斷增4
??? 常用的函數(shù)內(nèi)外跳轉(zhuǎn)指令有mov和BL,ARM有兩種跳轉(zhuǎn)方式:
? (1)mov pc, <跳轉(zhuǎn)地址〉
??? 這種向程序計數(shù)器PC直接寫跳轉(zhuǎn)地址,能在4GB連續(xù)空間內(nèi)任意跳轉(zhuǎn)。
? (2)通過 B BL BLX BX 可以完成在當(dāng)前指令向前或者向后32MB的地址空間的跳轉(zhuǎn)(為什么是32MB呢?寄存器是32位的,此時的值是24位有符號數(shù),所以32MB?后面再查查看)。B是最簡單的跳轉(zhuǎn)指令。要注意的是,跳轉(zhuǎn)指令的實際值不是絕對地址,而是相對地址——是相對當(dāng)前PC值的一個偏移量,它的值由匯編器計算得出。BL很常用,它在跳轉(zhuǎn)之前會在寄存器LR(R14)中保存PC的當(dāng)前內(nèi)容。BL的經(jīng)典用法如下:
??? bl NEXT?????? ; 跳轉(zhuǎn)到NEXT
??? ……
??? NEXT
??? ……
??? mov pc, lr??? ; 從子程序返回。
1.? ARM的棧幀
??? 先來看看ARM的棧幀布局圖:
????
??? 上圖描述的是ARM的棧幀布局方式,main stack frame為調(diào)用函數(shù)的棧幀,func1 stack frame為當(dāng)前函數(shù)(被調(diào)用者)的棧幀,棧底在高地址,棧向下增長。圖中FP就是棧基址,它指向函數(shù)的棧幀起始地址;SP則是函數(shù)的棧指針,它指向棧頂?shù)奈恢谩?span style="color:#0000f0;">ARM壓棧的順序很是規(guī)矩(也比較容易被黑客攻破么),依次為當(dāng)前函數(shù)指針PC、返回指針LR、棧指針SP、棧基址FP、傳入?yún)?shù)個數(shù)及指針、本地變量和臨時變量。如果函數(shù)準(zhǔn)備調(diào)用另一個函數(shù),跳轉(zhuǎn)之前臨時變量區(qū)先要保存另一個函數(shù)的參數(shù)。
??? ARM也可以用棧基址和棧指針明確標(biāo)示棧幀的位置,棧指針SP一直移動,相比于x86,ARM更為鮮明的特點是,兩個棧空間內(nèi)的地址(SP+FP)前面,必然有兩個代碼地址(PC+LR)明確標(biāo)示著調(diào)用函數(shù)位置內(nèi)的某個地址。 ? 2.? ARM的匯編指令和棧操作
??? ARM微處理器共有37個寄存器,其中31個為通用寄存器,6個為狀態(tài)寄存器。但是這些寄存器不能被同時訪問,具體哪些寄存器是可編程訪問的,取決于微處理器的工作狀態(tài)及具體的運行模式。但在任何時候,通用寄存器R0~R15、一個或兩個狀態(tài)寄存器都是可訪問的。有三個特殊的通用寄存器:
? 寄存器R13:在ARM指令中常用作堆棧指針SP
? 寄存器R14:也稱作子程序連接寄存器(Subroutine Link Register)即連接寄存器LR
? 寄存器R15:也稱作程序計數(shù)器PC
??? ARM進(jìn)行函數(shù)內(nèi)壓棧和出棧往往使用如下的語句:
??stmfd sp!, {r0-r9, lr}??? ;?滿遞減入棧,給寄存器r0-r9,lr壓棧,sp不斷減4
??ldmfd sp!, {r0-r9, pc}??? ; 滿遞減出棧,給寄存器r0-r9出棧,并使程序跳轉(zhuǎn)回函數(shù)的調(diào)用點,sp不斷增4
??? 常用的函數(shù)內(nèi)外跳轉(zhuǎn)指令有mov和BL,ARM有兩種跳轉(zhuǎn)方式:
? (1)mov pc, <跳轉(zhuǎn)地址〉
??? 這種向程序計數(shù)器PC直接寫跳轉(zhuǎn)地址,能在4GB連續(xù)空間內(nèi)任意跳轉(zhuǎn)。
? (2)通過 B BL BLX BX 可以完成在當(dāng)前指令向前或者向后32MB的地址空間的跳轉(zhuǎn)(為什么是32MB呢?寄存器是32位的,此時的值是24位有符號數(shù),所以32MB?后面再查查看)。B是最簡單的跳轉(zhuǎn)指令。要注意的是,跳轉(zhuǎn)指令的實際值不是絕對地址,而是相對地址——是相對當(dāng)前PC值的一個偏移量,它的值由匯編器計算得出。BL很常用,它在跳轉(zhuǎn)之前會在寄存器LR(R14)中保存PC的當(dāng)前內(nèi)容。BL的經(jīng)典用法如下:
??? bl NEXT?????? ; 跳轉(zhuǎn)到NEXT
??? ……
??? NEXT
??? ……
??? mov pc, lr??? ; 從子程序返回。
總結(jié)