寄存器擴(kuò)展
棧(SP&FP寄存器)
棧是一種特殊訪問(wèn)方式的存儲(chǔ)空間卧须。(先出后進(jìn)悴能、后進(jìn)先出)由高地址向低地址開(kāi)辟空間蛇券,如圖所示:
- SP寄存器在任意時(shí)刻會(huì)保存我們棧頂?shù)牡刂?/li>
- FP寄存器也就是x29寄存器崖疤,它屬于通用寄存器的一個(gè)仰冠,但是在某些時(shí)刻我們利用它保存棧底的地址!
關(guān)于內(nèi)存讀寫(xiě)指令
數(shù)據(jù)都是從高地址開(kāi)始讀寫(xiě)的U栋拧G嵯佟!
注意:從ARM64開(kāi)始划乖,取消32位的 LDM贬养、STM、PUSH琴庵、POP指令! 取而代之的是【ldr(單個(gè))误算、ldp(兩個(gè))】 【str(單個(gè))、stp(兩個(gè))】 ARM64里面 對(duì)棧的操作是16字節(jié)對(duì)齊的C缘睢6瘛!
str(store register)指令
將數(shù)據(jù)從寄存器中讀出來(lái),存到內(nèi)存中庆寺。stp指令是str的變種指令蚊夫,可以同時(shí)操作2個(gè)寄存器。
ldr(load register)指令
將數(shù)據(jù)從內(nèi)存中讀出來(lái),存到寄存器中懦尝。ldp指令是ldr的變種指令知纷,可以同時(shí)操作2個(gè)寄存器壤圃。
函數(shù)調(diào)用棧
常見(jiàn)的函數(shù)調(diào)用開(kāi)辟棧和恢復(fù)棧空間
sub sp, sp, #0x80 ; 拉伸0x80(128字節(jié))空間
stp x29, x30, [sp, #0x70] ;x29/x30 寄存器入棧保護(hù)
add x29, sp, #0x70 ; x29指向棧幀的底部
...
ldp x29, x30, [sp, #0x70] ;恢復(fù)x29/x30 寄存器的值
add sp, sp, #0x80 ; 棧平衡
ret
堆棧操作練習(xí)
使用32個(gè)字節(jié)空間作為這段程序的椑旁空間,然后利用棧將x0和x1的值進(jìn)行交換伍绳。
sub sp,sp,#0x20 ;開(kāi)辟32字節(jié)空間
stp x0,x1,[sp,#0x10] ;sp往上加16字節(jié)存放x0,x1
ldp x1,x0,[sp,#0x10] ;將內(nèi)存作為temp 取出x0的值賦值給x1,取出x1的值給x0
add sp,sp,#0x20 ;恢復(fù)棧平衡
bl指令和ret指令
bl指令
將下一條指令的地址放入lr(x30)寄存器,轉(zhuǎn)到標(biāo)號(hào)處執(zhí)行指令
ret指令
默認(rèn)使用lr(x30)寄存器的值,通過(guò)底層指令提示CPU此處作為下條指令地址!
ARM64平臺(tái)的特色指令,它面向硬件做了優(yōu)化處理的
lr寄存器
lr寄存器就是x30寄存器乍桂,也是通用寄存器的一個(gè)冲杀,存放的是函數(shù)的返回地址。當(dāng)ret指令執(zhí)行時(shí)模蜡,會(huì)尋找x30寄存器保存的地址值漠趁!
注意:在函數(shù)嵌套調(diào)用的時(shí)候,需要將x30入棧H碳病4炒!否則會(huì)出現(xiàn)死循環(huán)無(wú)法跳出B倍省I獭!
函數(shù)的參數(shù)和返回值
- 參數(shù)
ARM64下,函數(shù)的參數(shù)是存放在X0到X7(W0到W7)這8個(gè)寄存器里面的则披,如果超過(guò)8個(gè)參數(shù)共缕,就會(huì)入棧。
OC方法最好不要超過(guò)6個(gè)參數(shù)士复,因?yàn)镺C方法有兩個(gè)隱形參數(shù)(id self , SEL _cmd)
- 返回值
函數(shù)的返回值是放在X0 寄存器里面的图谷。