寄存器 :
ARM64中? ??64位: X0-X30, XZR(零寄存器)? ?32位: W0-W30, WZR(零寄存器)
PC 寄存器, 如果需要改變PC 寄存器诀黍,需要用到 bl 跳轉指令
椩捍伲空間是通過操作sp寄存器開辟的空間
SP和FP寄存器
sp寄存器在任意時刻會保存我們棧頂?shù)牡刂? sp往高地址走都是棧區(qū)域,sp往低地址走是沒用的嫂易。
fp寄存器也稱為x29寄存器屬于通用寄存器,但是在某些時刻我們利用它保存棧底的地址!
注意:ARM64開始,取消32位的 LDM,STM,PUSH,POP指令! 取而代之的是ldr\ldp str\stp
ARM64里面 對棧的操作是16字節(jié)對齊的!!
在arm64 中不存在 push pop操作兄朋,如果往棧區(qū)域讀寫信息怜械,用的是 str (從寄存器寫入到內存)、ldr (從內存中讀取到寄存器中)
進入函數(shù)會開辟椔圃剩空間峡扩,函數(shù)調用完畢,會將棧中的數(shù)據(jù)釋放障本,叫做棧平衡。(函數(shù)調用之前和之后巍佑,棧的sp 寄存器指向的位置是不變的寄悯,開辟的時候 sp -,釋放的時候 sp + )
bl和ret指令
bl標號(跳轉脆栋,跳到指定的函數(shù)地址)
將下一條指令的地址放入lr(x30)寄存器
轉到標號處執(zhí)行指令
ret(返回回去)
默認使用lr(x30)寄存器的值,通過底層指令提示CPU此處作為下條指令地址!
ARM64平臺的特色指令,它面向硬件做了優(yōu)化處理的
x30寄存器(回去的路)
x30寄存器存放的是函數(shù)的返回地址.當ret指令執(zhí)行時刻,會尋找x30寄存器保存的地址值!
注意:在函數(shù)嵌套調用的時候.需要講x30入棧!
這種寫法會造成最終無法回到main 函數(shù)中洒擦,在 A函數(shù)中一直死循環(huán),因為 main 到A中x30寄存器保存了回家的路秦踪,但是A到B是,x30保存了A的bl下一條指令的地址柠逞,所以在B ret后會一直在A中死循環(huán)景馁。
?0x10120a948<+0>:? stp? ? x29, x30, [sp,#-0x10]!? ?(相當于 x -= x)
stp 也是一種寫入的指令。將 x29 x30 放到 sp 減去 16個字節(jié)的位置绰精,并且將sp 減去 0x10,
?? 0x10120a954<+12>: ldp? ? x29, x30, [sp],#0x10
將當前的值取出來賦值給x29 x30 透葛,然后 把sp 的值加上 0x10,
這種指令只能在棧空間只需要保護 x29 x30,只有簡單的調用获洲,局部變量也么有殿如。
ldr : r? 取出來16個字節(jié)涉馁, ldp : p 取出來 32個字節(jié)
[sp] 的意思是,把sp作為一個內存地址寒随,取出該內存地址中的值帮坚。
str x30,[sp,#-0x10]!? ?意思是, 以?sp,#-0x10 為尋址试和,把x30的值放到 [sp,#-0x10] 內存地址中阅悍,x寄存器是8個字節(jié)
ARM64對棧的操作是 16個字節(jié)對齊的,所以挪動 sp 一定是16的倍數(shù)节视。
w8是x8寄存器的低32位寻行,把x8的值給了x0,? w 寄存器就是 x 寄存器的低 地址的寄存器,高地址的全為0, 節(jié)約內存是在寫入到棧區(qū)的時候節(jié)約的
64位: X0-X30, XZR(零寄存器)
32位: W0-W30, WZR(零寄存器)
函數(shù)的參數(shù)和返回值
ARM64下,函數(shù)的參數(shù)是存放在X0到X7(W0到W7)這8個寄存器里面的.如果超過8個參數(shù),就會入棧.
函數(shù)的返回值?是放在X0 寄存器里面的.
當我們的棧空間給別人用的時候连躏,給接下來的函數(shù)調用棧使用時入热,棧區(qū)域從棧頂 sp 開始存放數(shù)據(jù),如果存放自己的數(shù)據(jù)勺良,從棧底 x29 開始的尚困。
超過了8個參數(shù),需要用到棧事甜,通過寄存器的訪問最高效。