ARM64匯編學(xué)習(xí)筆記二(寄存器和函數(shù)本質(zhì))

寄存器

CPU除了有控制器、運(yùn)算器還有寄存器丹鸿。其中寄存器的作用就是進(jìn)行數(shù)據(jù)的臨時存儲越走。

CPU的運(yùn)算速度是非常快的靠欢,為了性能CPU在內(nèi)部開辟一小塊臨時存儲區(qū)域廊敌,并在進(jìn)行運(yùn)算時先將數(shù)據(jù)從內(nèi)存復(fù)制到這一小塊臨時存儲區(qū)域中,運(yùn)算時就在這一小快臨時存儲區(qū)域內(nèi)進(jìn)行门怪。我們稱這一小塊臨時存儲區(qū)域?yàn)榧拇嫫鳌?/p>

對于arm64系的CPU來說骡澈, 如果寄存器以x開頭則表明的是一個64位的寄存器,如果以w開頭則表明是一個32位的寄存器掷空,其中32位的寄存器是64位寄存器的低32位部分并不是獨(dú)立存在的肋殴。注意在系統(tǒng)中沒有提供16位和8位的寄存器供訪問和使用。

高速緩存(了解)

iPhoneX上搭載的ARM處理器A11它的1級緩存的容量是64KB坦弟,2級緩存的容量8M护锤。

CPU每執(zhí)行一條指令前都需要從內(nèi)存中將指令讀取到CPU內(nèi)并執(zhí)行。而寄存器的運(yùn)行速度相比內(nèi)存讀寫要快很多,為了性能,CPU還集成了一個高速緩存存儲區(qū)域.當(dāng)程序在運(yùn)行時酿傍,先將要執(zhí)行的指令代碼以及數(shù)據(jù)復(fù)制到高速緩存中去(由操作系統(tǒng)完成).CPU直接從高速緩存依次讀取指令來執(zhí)行.

數(shù)據(jù)地址寄存器

數(shù)據(jù)地址寄存器通常用來做數(shù)據(jù)計(jì)算的臨時存儲烙懦、做累加、計(jì)數(shù)赤炒、地址保存等功能氯析。定義這些寄存器的作用主要是用于在CPU指令中保存操作數(shù),在CPU中當(dāng)做一些常規(guī)變量來使用莺褒。
ARM64中

  • 64位的數(shù)據(jù): X0-X30, XZR(零寄存器)
  • 32位的數(shù)據(jù): W0-W30, WZR(零寄存器)


浮點(diǎn)寄存器

因?yàn)楦↑c(diǎn)數(shù)的存儲以及其運(yùn)算的特殊性,CPU中專門提供浮點(diǎn)數(shù)寄存器來處理浮點(diǎn)數(shù)
ARM64中

  • 64位的數(shù)據(jù): D0 - D31
  • 32位的數(shù)據(jù): S0 - S31


向量寄存器

現(xiàn)在的CPU支持向量運(yùn)算.(向量運(yùn)算在圖形處理相關(guān)的領(lǐng)域用得非常的多)為了支持向量計(jì)算掩缓,系統(tǒng)也提供了眾多的向量寄存器
128位的數(shù)據(jù):V0 - V31


棧是一種具有特殊訪問方式的存儲空間(特性:先進(jìn)后出 - First In Last Out,后進(jìn)先出 - Last In First Out)


函數(shù)調(diào)用會開辟一段內(nèi)存空間(椬裱遥空間)用于函數(shù)的局部變量拾因、參數(shù)和寄存器的保護(hù)

sub sp, sp,#0x20           ;拉伸棧空間

函數(shù)調(diào)用完畢之后也需要釋放空間

add sp, sp, #0x20          ;棧平衡

補(bǔ)充:sp拉伸空間的大小是根據(jù)什么旷余?
函數(shù)的參數(shù)和局部變量的內(nèi)存空間大小 + x29、x30的內(nèi)存空間大小
拉伸空間的大小最少為16字節(jié)扁达,并且必須是16字節(jié)的倍數(shù)

sp 和 fp 寄存器

  • sp寄存器在任意時刻會保存棧頂?shù)牡刂?/li>
  • fp寄存器也稱為x29寄存器屬于通用寄存器,但是在某些時刻我們利用它保存棧底的地址

注意:
1.ARM64 開始就取消了32位的 LDM,STM,PUSH,POP指令正卧,取而代之的是str\stp、ldr\ldp
2.ARM64 里面對棧的操作是16字節(jié)對齊

內(nèi)存讀寫指令

注意:讀/寫數(shù)據(jù)都是往高地址讀/寫

str(store register)指令
將數(shù)據(jù)從寄存器中讀出來,存到內(nèi)存中

ldr(load register)指令
將數(shù)據(jù)從內(nèi)存中讀出來,存到寄存器中

此 ldr 和 str 的變種 ldp 和 stp 還可以操作2個寄存器

棧操作

練習(xí):使用32個字節(jié)空間作為這段程序的椆蚪猓空間,然后利用棧將x0和x1的值進(jìn)行交換

.text
.global _A
_A:
   mov x0, #0xa               ;x0=10
   mov x1, #0xc               ;x1=12
   sub sp, sp,#0x20           ;拉伸椔酰空間
   stp x0, x1, [sp, #0x10]    ;sp棧偏移16字節(jié)寫入x0,x1
   ldp x1, x0, [sp, #0x10]    ;sp棧偏移16字節(jié)讀取x1,x0
   add sp, sp, #0x20          ;棧平衡(每個函數(shù)調(diào)用完畢之后,將拉伸的棧空間平衡(將sp加回去))
   ret

bl 和 ret 指令

bl 指令--跳轉(zhuǎn)

  • 將下一條指令的地址放入 lr(x30)寄存器窘行,保存回家的地址
  • 跳轉(zhuǎn)到標(biāo)號處執(zhí)行指令

rec 指令--返回

  • 返回到 lr 寄存器所保存的地址
  • pc 寄存器指向此地址饥追,并執(zhí)行下一步指令

注意:x30寄存器存放的是函數(shù)的返回地址,當(dāng)ret指令執(zhí)行時刻罐盔,會尋找x30寄存器保存的地址值

函數(shù)的本質(zhì)

函數(shù)的參數(shù)

在 ARM64 中但绕,函數(shù)的參數(shù)是保存在X0-X7(W0-W7)這8個寄存器里面,如果超過8個參數(shù)惶看,超過的參數(shù)會入棧捏顺,保存在棧里面。

調(diào)用函數(shù)一:(這種情況是參數(shù)個數(shù)不超過8)

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int sum1(int a, int b) {
    return a + b;
}

int main(int argc, char * argv[]) {
    sum1(10, 20);
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
  • 未調(diào)用函數(shù)時的匯編代碼
  • 進(jìn)入函數(shù)后的匯編代碼

調(diào)用函數(shù)二:(這種情況是參數(shù)個數(shù)超過8)

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int sum2(int a, int b, int c, int d, int e, int f, int g, int h, int i) {
    int sum = a + b + c + d + e + f + g + h + i;
    return sum;
}

int main(int argc, char * argv[]) {
    sum2(1, 2, 3, 4, 5, 6, 7, 8, 9);
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
  • 未調(diào)用函數(shù)時的匯編代碼
  • 進(jìn)入函數(shù)后的匯編代碼

函數(shù)的局部變量

在 ARM64 中纬黎,函數(shù)的局部變量保存在棧里面幅骄。

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int sum3() {
    int a = 10;
    int b = 20;
    return a + b;
}

int main(int argc, char * argv[]) {
    sum3();
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
  • 未調(diào)用函數(shù)時的匯編代碼
  • 進(jìn)入函數(shù)后的匯編代碼

通過調(diào)用函數(shù)的前后匯編代碼可以發(fā)現(xiàn)函數(shù)的局部變量保存在棧里面,當(dāng)函數(shù)調(diào)用完之后本今,保持棧平衡拆座,就是我們所謂的釋放內(nèi)存空間,其實(shí)真正意義上是此數(shù)據(jù)仍在內(nèi)存中冠息,只是此時沒法直接訪問到挪凑,等待下一次其他數(shù)據(jù)的覆蓋。

函數(shù)的返回值

在 ARM64 中铐达,函數(shù)的返回值保存在 x0寄存器

函數(shù)的嵌套調(diào)用

注意事項(xiàng):
1.當(dāng)此函數(shù)為葉子函數(shù)時岖赋,就不需要在對 x29 和 x30 寄存器的保護(hù)。
葉子函數(shù):函數(shù)里面不再調(diào)用其他函數(shù)瓮孙。
2.當(dāng)函數(shù)中的參數(shù)還有其他函數(shù)的引用時唐断,需要對參數(shù)入棧,進(jìn)行保護(hù)杭抠,以防引起數(shù)據(jù)錯誤脸甘。

葉子函數(shù)

//葉子函數(shù)
int funcA(int a, int b) {
    return a+b;
}

//非葉子函數(shù)
void funcB() {
    printf("haha");    //調(diào)用 printf 函數(shù)
}
funcA 匯編代碼
funcB 匯編代碼

明顯可以發(fā)現(xiàn)葉子函數(shù)并沒有做任何對 x29 和 x30 寄存器的保護(hù)。

函數(shù)嵌套

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int funcA(int a, int b) {
    return a+b;
}

int funcC(int a, int b) {
    int c = funcA(a, b);
    int d = funcA(a, b);
    return c+d;
}

int main(int argc, char * argv[]) {
    funcC(10, 20);
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末偏灿,一起剝皮案震驚了整個濱河市丹诀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翁垂,老刑警劉巖铆遭,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異沿猜,居然都是意外死亡枚荣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門啼肩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來橄妆,“玉大人衙伶,你說我怎么就攤上這事『δ耄” “怎么了矢劲?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長慌随。 經(jīng)常有香客問我芬沉,道長,這世上最難降的妖魔是什么儒陨? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任花嘶,我火速辦了婚禮,結(jié)果婚禮上蹦漠,老公的妹妹穿的比我還像新娘椭员。我一直安慰自己,他們只是感情好笛园,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布隘击。 她就那樣靜靜地躺著,像睡著了一般研铆。 火紅的嫁衣襯著肌膚如雪埋同。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天棵红,我揣著相機(jī)與錄音凶赁,去河邊找鬼。 笑死逆甜,一個胖子當(dāng)著我的面吹牛虱肄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播交煞,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼咏窿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了素征?” 一聲冷哼從身側(cè)響起集嵌,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎御毅,沒想到半個月后根欧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡端蛆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年咽块,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片欺税。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡侈沪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出晚凿,到底是詐尸還是另有隱情亭罪,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布歼秽,位于F島的核電站应役,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏燥筷。R本人自食惡果不足惜箩祥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肆氓。 院中可真熱鬧袍祖,春花似錦、人聲如沸谢揪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拨扶。三九已至凳鬓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間患民,已是汗流浹背缩举。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留匹颤,地道東北人仅孩。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像惋嚎,于是被迫代替她去往敵國和親杠氢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容