內(nèi)存分區(qū)
- 堆區(qū) (Heap)
特點:動態(tài)申請 可讀可寫
- 棧區(qū) (Stack)
特點:由系統(tǒng)進(jìn)行內(nèi)存的管理。主要存放函數(shù)的參數(shù)以及局部變量。
在函數(shù)完成執(zhí)行,系統(tǒng)自行釋放棧區(qū)內(nèi)存,不需要用戶管理。
- 代碼區(qū)
存放程序的二進(jìn)制代碼。比如我們寫的函數(shù),都是在代碼區(qū)的。特點: 可讀可寫可執(zhí)行,存放程序編譯后的二進(jìn)制代碼,不可尋址區(qū)。
- 全局/靜態(tài)存儲區(qū)
特點:可讀可寫
靜態(tài)存儲區(qū)內(nèi)的變量在程序編譯階段已經(jīng)分配好內(nèi)存空間并初始化。這塊內(nèi)存在程序的整個運行期間都存在,它主要存放靜態(tài)變量、全局變量和常量。
包括:常量區(qū)(靜態(tài)常量區(qū)),全局區(qū)(全局變量區(qū))和靜態(tài)變量區(qū)(靜態(tài)區(qū))。
- 常量區(qū)
特點: 只讀!
字符串常量區(qū)和常變量區(qū)。
計算機(jī)尋找原理
如以下的函數(shù):
int f = 10;
int func (int a, int b){
printf("hahha");
int c = a + f;
return c;
}
int main(int argc, char * argv[]) {
printf("%d",func(1, 2));
return 0;
}
尋找常量和全局變量:

注意上面的 adrp 指令 (adrp:address page 常量)
adrp x0, 1
1. 將1的值,左移12位 1 0000 0000 0000 == 0x1000
2.將PC寄存器的低12位清零 pc = 0x0000000100fe2874; 0x100fe2874 ==> 0x100fe2000
3.將將1 和 2 的結(jié)果相加 給 X0 寄存器!!
adrp 是計算指定的數(shù)據(jù)地址 到當(dāng)前PC值的相對偏移;
由于得到的結(jié)果是低12bit為0,
2^10 == 1024 Byte
2^12 == 4KB
所以要尋找的地址和當(dāng)前 pc 的值的誤差即4 kb, 也就是要尋找的(常量所在的)地址一定會在這 4KB 里面?,F(xiàn)在找到的是一個粗略的基址,以這個基址可以在(再加上)偏移4 kb 的范圍內(nèi)找到。
要算準(zhǔn)確的地址呢?
第二句:add x0, x0, #0xf28 中的偏移 #0xf28,計算機(jī)編譯的時候知道的偏移地址,和此時的 pc 為:
Printing description of $pc:
(unsigned long) pc = 0x0000000100fe2888
可以得到:
0x100fe2888—> 0x100fe3000—>0x100fe3f28
計算過程:
p (char *) 0x100fe2000 + 0x1000 + 0xf28 = 0x100fe3f28
可以看到結(jié)果如下:

第二個 adrp (全局變量)
此時的 (unsigned long) pc = 0x0000000100fe2894
通過推算,準(zhǔn)確的地址為:0x0000000100fe4d10
打印結(jié)果如下:

可以看到,找到的則為全局變量 f 的值。
注意:需要說明的一點是:要打印地址的值,即為指針做指向的值,p (Int *) 打印的還是這個地址,要打印該地址的值則為:p *(int *) + 地址。