寄存器的本質(zhì)
寄存器從大一的計(jì)算機(jī)組成原理就開始聽到它,感覺很神秘,如夢如霧多年.揭開本質(zhì)后才發(fā)現(xiàn),寄存器就是一個(gè)32位的存儲(chǔ)空間,一個(gè)int變量而已,但它的厲害之處在于極高頻率的使用,讓人不敢相信是怎么做到的,不管再復(fù)雜再牛牛的應(yīng)用程序,電商也好,游戲,直播也罷,到了它這里都變成了有限的十幾個(gè)寄存器在玩,簡直太神奇了. 本篇將清楚說明寄存器的數(shù)量和功能,至于它是如何把復(fù)雜的上層程序變成了這十幾個(gè)寄存器來玩?這是編譯器的事情,不在討論范圍之內(nèi).
在 32 位的 ARM 架構(gòu)中,核心寄存器(core register)的數(shù)量一般有 37 個(gè)或者更多,視處理器實(shí)現(xiàn)的功能多少而定。所謂核心寄存器就是指 ARM 處理器內(nèi)核執(zhí)行常規(guī)指令時(shí)使用的寄存器,不包括用于浮點(diǎn)計(jì)算和 SIMD 技術(shù)的特殊寄存器,也可以理解為是 ARM 的核心處理器單元(PE)中的寄存器,不包括外圍的協(xié)處理器中的寄存器。
ARM7的37個(gè)寄存器,具體看圖說明:
這些寄存器不能同時(shí)顯示,處理器指令狀態(tài)和工作模式指定哪些寄存器可供使用,圖中一一對應(yīng).
其中31個(gè)通用32位寄存器,系統(tǒng)和用戶模式全程復(fù)用寄存器,而其余5中異常(或叫特權(quán))模式從R8_* ~ R14_* 的寄存器叫模式專屬寄存器.這種特征的寄存器有個(gè)專門的稱呼,叫 Banked register。Bank 本意是銀行和存款的意思,在這里的意思是"有備份的".
注意 r8 和 r8_fiq是兩個(gè)不同的寄存器,名字前綴是為了好記,管理方便,以示同級概念理解.如此湊成了31個(gè)寄存器.
其中r13寄存器用于SP寄存器,始終指向棧頂,因?yàn)槊糠N工作模式都有獨(dú)立的運(yùn)行棧,所以有獨(dú)立的寄存器去記住各自的棧頂.
同理r14寄存器用于LR寄存器,用于保存模式切換時(shí)的切換位置,也是獨(dú)立存在,說明模式間回跳時(shí)并不需要重新給r14_*賦值,只需在跳出去的時(shí)候保存即可.
系統(tǒng)和用戶模式共用r13(sp)和r14(lr)寄存器,所以在每個(gè)子函數(shù)的棧幀中都要保存上一個(gè)調(diào)用它函數(shù)的SP和LR值,自己執(zhí)行完成后要從棧幀中恢復(fù)這兩個(gè)寄存器的值,否則無法界定回去后從哪里開始,從哪里計(jì)算偏移位置.
r15(pc)寄存器是指向代碼段的,所有模式復(fù)用的原因是它是共用的,一份代碼,你運(yùn)行與不運(yùn)行,代碼段就在哪里,不增不減.
6個(gè)狀態(tài)寄存器,其中CPSR(1個(gè))和SPSR_*(5個(gè)),它們主要用于自運(yùn)行或發(fā)生模式切換后的各種狀態(tài)保存.
CPSR:程序狀態(tài)寄存器(current program status register) (當(dāng)前程序狀態(tài)寄存器),在任何處理器模式下被訪問。
SPSR:程序狀態(tài)保存寄存器(saved program status register),每一種處理器模式下都有一個(gè)狀態(tài)寄存器SPSR,SPSR用于保存CPSR的狀態(tài),以便異常返回后恢復(fù)異常發(fā)生時(shí)的工作狀態(tài)。當(dāng)特定 的異常中斷發(fā)生時(shí),這個(gè)寄存器用于存放當(dāng)前程序狀態(tài)寄存器的內(nèi)容。在異常中斷退出時(shí),可以用SPSR來恢復(fù)CPSR。
七種工作模式
關(guān)于工作模式在鴻蒙內(nèi)核源碼分析(總目錄)之工作模式篇中有詳細(xì),可自行前往查看.此處只簡單說明下. 下圖來源于ARM720T.pdf第43頁,在ARM體系中,CPU工作在以下七種模式中:
用戶模式(usr):該模式是用戶程序的工作模式,它運(yùn)行在操作系統(tǒng)的用戶態(tài),它沒有權(quán)限去操作其它硬件資源,只能執(zhí)行處理自己的數(shù)據(jù),也不能切換到其它模式下,要想訪問硬件資源或切換到其它模式只能通過軟中斷或產(chǎn)生異常。
快速中斷模式(fiq):快速中斷模式是相對一般中斷模式而言的,用來處理高優(yōu)先級中斷的模式,處理對時(shí)間要求比較緊急的中斷請求,主要用于高速數(shù)據(jù)傳輸及通道處理中。
普通中斷模式(irq):一般中斷模式也叫普通中斷模式,用于處理一般的中斷請求,通常在硬件產(chǎn)生中斷信號之后自動(dòng)進(jìn)入該模式,該模式可以自由訪問系統(tǒng)硬件資源。
管理模式(svc):操作系統(tǒng)保護(hù)模式,CPU上電復(fù)位和當(dāng)應(yīng)用程序執(zhí)行 SVC 指令調(diào)用系統(tǒng)服務(wù)時(shí)也會(huì)進(jìn)入此模式,操作系統(tǒng)內(nèi)核的普通代碼通常工作在這個(gè)模式下。
終止模式(abt):當(dāng)數(shù)據(jù)或指令預(yù)取終止時(shí)進(jìn)入該模式,中止模式用于支持虛擬內(nèi)存或存儲(chǔ)器保護(hù),當(dāng)用戶程序訪問非法地址,沒有權(quán)限讀取的內(nèi)存地址時(shí),會(huì)進(jìn)入該模式,
系統(tǒng)模式(sys):供操作系統(tǒng)使用的高特權(quán)用戶模式,與用戶模式類似,但具有可以直接切換到其他模式等特權(quán),用戶模式與系統(tǒng)模式兩者使用相同的寄存器,都沒有SPSR(Saved Program Statement Register,已保存程序狀態(tài)寄存器),但系統(tǒng)模式比用戶模式有更高的權(quán)限,可以訪問所有系統(tǒng)資源。
未定義模式(und):未定義模式用于支持硬件協(xié)處理器的軟件仿真,CPU在指令的譯碼階段不能識(shí)別該指令操作時(shí),會(huì)進(jìn)入未定義模式。
除用戶模式外,其余6種工作模式都屬于特權(quán)模式
特權(quán)模式中除了系統(tǒng)模式以外的其余5種模式稱為異常模式
大多數(shù)程序運(yùn)行于用戶模式
進(jìn)入特權(quán)模式是為了處理中斷、異常、或者訪問被保護(hù)的系統(tǒng)資源
硬件權(quán)限級別:系統(tǒng)模式 > 異常模式 > 用戶模式
快中斷(fiq)與慢中斷(irq)區(qū)別:快中斷處理時(shí)禁止中斷
每種模式都有自己獨(dú)立的入口和獨(dú)立的運(yùn)行??臻g.系列篇之CPU篇已介紹過只要提供了入口函數(shù)和運(yùn)行空間,CPU就可以干活了.入口函數(shù)解決了指令來源問題,運(yùn)行空間解決了指令的運(yùn)行場地問題. 而且在多核情況下,每個(gè)CPU核的每種特權(quán)模式都有自己獨(dú)立的棧空間.注意是特權(quán)模式下的??臻g,用戶模式的??臻g是由用戶(應(yīng)用)程序提供的.
R0~R7 寄存器
這 8 個(gè)寄存器是最普通的,所有模式都可以訪問和使用. 尤其是R0是寄存器中的王牌,被稱為頭號寄存器,通用寄存器中它用的最高頻,隨便翻段匯編代碼都能看到它的影子.鴻蒙開機(jī)第一跳指令就是 r0 = 0
reset_vector: //鴻蒙開機(jī)代碼 /* clear register TPIDRPRW */ mov r0, #0 @r0 = 0 mcr p15, 0, r0, c13, c0, 4 @c0,c13 = 0, C13為進(jìn)程標(biāo)識(shí)符 含義見 ARM720T.PDF 第64頁 /* do some early cpu setup: i/d cache disable, mmu disabled */ @禁用MMU, i/d緩存 mrc p15, 0, r0, c1, c0, 0 @r0 = c1 ,c1寄存器詳細(xì)解釋見第64頁 bic r0, #(1<<12) @位清除指令,清除r0的第11位 bic r0, #(1<<2 | 1<<0) @清除第0和2位 ,禁止 MMU和緩存 0位:MMU enable/disable 2位:Cache enable/disable mcr p15, 0, r0, c1, c0, 0 @c1=r0
再看拿自旋鎖的匯編代碼,這些代碼都在系列篇中詳細(xì)講解過,可前往鴻蒙內(nèi)核源碼分析(總目錄)自行查看.
FUNCTION(ArchSpinLock) @非要拿到鎖 mov r1, #1 @r1=1 1: @循環(huán)的作用,因SEV是廣播事件.不一定lock->rawLock的值已經(jīng)改變了 ldrex r2, [r0] @r0 = &lock->rawLock, 即 r2 = lock->rawLock cmp r2, #0 @r2和0比較 wfene @不相等時(shí),說明資源被占用,CPU核進(jìn)入睡眠狀態(tài) strexeq r2, r1, [r0]@此時(shí)CPU被重新喚醒,嘗試令lock->rawLock=1,成功寫入則r2=0 cmpeq r2, #0 @再來比較r2是否等于0,如果相等則獲取到了鎖 bne 1b @如果不相等,繼續(xù)進(jìn)入循環(huán) dmb @用DMB指令來隔離,以保證緩沖中的數(shù)據(jù)已經(jīng)落實(shí)到RAM中 bx lr @此時(shí)是一定拿到鎖了,跳回調(diào)用ArchSpinLock函數(shù)
R0被潛規(guī)則的干了兩件事,突出了它的重要性:
第一個(gè)參數(shù) 由R0保管,當(dāng)然第二個(gè)參數(shù)就給R1保管
函數(shù)的返回值統(tǒng)一交給R0保管, 例如 a -> b ,b執(zhí)行完會(huì)把返回值給r0,回到a后,a從r0取值,不管取到什么,它就認(rèn)為這是b的返回值,默認(rèn)都只認(rèn)r0保存了返回值,這就是規(guī)定.
具體看一個(gè)C函數(shù)和它的匯編,在系列篇也已經(jīng)講過,可自行翻看.
//++++++++++++ square(c -> 匯編)++++++++++++++++++++++++ int square(int a,int b){ return a*b; } square(int, int): sub sp, sp, #8 @sp減去8,意思為給square分配??臻g,只用2個(gè)棧空間完成計(jì)算 str r0, [sp, #4] @第一個(gè)參數(shù)入棧 str r1, [sp] @第二個(gè)參數(shù)入棧 ldr r1, [sp, #4] @取出第一個(gè)參數(shù)給r1 ldr r2, [sp] @取出第二個(gè)參數(shù)給r2 mul r0, r1, r2 @執(zhí)行a*b給R0,返回值的工作一直是交給R0的 add sp, sp, #8 @函數(shù)執(zhí)行完了,要釋放申請的??臻g bx lr @子程序返回,等同于mov pc,lr,即跳到調(diào)用處 //++++++++++++ fp(c -> 匯編)++++++++++++++++++++++++ int fp(int b) { int a = 1; return square(a+b,a+b); } fp(int): push {r11, lr} @r11(fp)/lr入棧,保存調(diào)用者main的位置 mov r11, sp @r11用于保存sp值,函數(shù)棧開始位置 sub sp, sp, #8 @sp減去8,意思為給fp分配棧空間,只用2個(gè)??臻g完成計(jì)算 str r0, [sp, #4] @先保存參數(shù)值,放在SP+4,此時(shí)r0中存放的是參數(shù) mov r0, #1 @r0=1 str r0, [sp] @再把1也保存在SP的位置 ldr r0, [sp] @把SP的值給R0 ldr r1, [sp, #4] @把SP+4的值給R1 add r1, r0, r1 @執(zhí)行r1=a+b mov r0, r1 @r0=r1,用r0,r1傳參 bl square(int, int)@先mov lr, pc 再mov pc square(int, int) mov sp, r11 @函數(shù)執(zhí)行完了,要釋放申請的??臻g pop {r11, lr} @彈出r11和lr,lr是專用標(biāo)簽,彈出就自動(dòng)復(fù)制給lr寄存器 bx lr @子程序返回,等同于mov pc,lr,即跳到調(diào)用處
這段代碼同樣適用于理解以下的各個(gè)寄存器.R0的作用相當(dāng)于 x86 的 EAX
R7 寄存器
為啥要單獨(dú)講R7寄存器,因?yàn)樗紶栕鳛樘厥饧拇嫫髟谑褂?內(nèi)核對上層應(yīng)用提供了數(shù)百個(gè)系統(tǒng)調(diào)用功能,當(dāng)發(fā)生系統(tǒng)調(diào)用時(shí),在CPU工作模式切換過程中,系統(tǒng)調(diào)用號是一直保存在R7寄存器中的,通過系統(tǒng)調(diào)用號就能查詢到對應(yīng)的注冊函數(shù).具體在 系統(tǒng)調(diào)用篇中有詳細(xì)的過程說明,這里只列出部分代碼
//4個(gè)參數(shù)的系統(tǒng)調(diào)用時(shí)底層處理 static inline long __syscall4(long n, long a, long b, long c, long d) { register long a7 __asm__("a7") = n; //將系統(tǒng)調(diào)用號保存在R7寄存器 register long a0 __asm__("a0") = a; //R0 register long a1 __asm__("a1") = b; //R1 register long a2 __asm__("a2") = c; //R2 register long a3 __asm__("a3") = d; //R3 __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3)) } //切換到SVC模式后,由匯編代碼調(diào)用由C語言實(shí)現(xiàn)的系統(tǒng)調(diào)用統(tǒng)一入口 LITE_OS_SEC_TEXT UINT32 *OsArmA32SyscallHandle(UINT32 *regs) { UINT32 ret; UINT8 nArgs; UINTPTR handle; UINT32 cmd = regs[REG_R7];// 從R7寄存器中取出系統(tǒng)調(diào)用號 handle = g_syscallHandle[cmd];//查詢系統(tǒng)調(diào)用的注冊函數(shù) //... }
fp(R11) 寄存器
R11:可以用作通用寄存器,在開啟特定編譯選項(xiàng)時(shí)可以用作幀指針寄存器FP,用來實(shí)現(xiàn)?;厮莨δ堋?GNU編譯器(gcc)默認(rèn)將R11作為存儲(chǔ)變量的通用寄存器,因而默認(rèn)情況下無法使用FP的棧回溯功能。為支持調(diào)用棧解析功能,需要在編譯參數(shù)中添加-fno-omit-frame-pointer選項(xiàng),提示編譯器將R11作為FP使用。
FP寄存器(Frame Point),幀指針寄存器,指向當(dāng)前函數(shù)的父函數(shù)的棧幀起始地址。利用該寄存器可以得到父函數(shù)的棧幀,從棧幀中獲取父函數(shù)的FP,就可以得到祖父函數(shù)的棧幀,以此類推,可以追溯程序調(diào)用棧,得到函數(shù)間的調(diào)用關(guān)系。
在鴻蒙內(nèi)核R11是當(dāng)FP寄存器使用.
SP(R13) 寄存器
SP:棧指針寄存器(stack pointer),它也是 banked register,而且所有模式都有一份,總共有 6 個(gè)(有虛擬化支持時(shí)再多一個(gè)),分別用于用戶、IRQ、FIQ、 未定義、中止和管理員模式。在 ARM 手冊,有時(shí)用 SP_usr、SP_svc 這樣的寫法來表示不同模式下的 SP 寄存器。
SP指向函數(shù)棧的棧頂,如此 fp 和 sp 就劃定了函數(shù)棧的范圍,函數(shù)在運(yùn)行期間除了動(dòng)態(tài)申請的內(nèi)存要跑出去玩,其余就在這塊空間里玩.
在鴻蒙內(nèi)核R13是當(dāng)SP寄存器使用.
LR(R14) 寄存器
又叫 Link Register,簡稱 LR,在主動(dòng)調(diào)用子函數(shù)時(shí),ARM 處理器會(huì)自動(dòng)將子函數(shù)的返回地址放到這個(gè)寄存器中。 另外在異常發(fā)生的被動(dòng)階段,會(huì)導(dǎo)致程序正常運(yùn)行的被打斷, 并將控制流轉(zhuǎn)移到相應(yīng)的異常處理(異常響應(yīng)),有些異常(fiq、irq)事件處理后,系統(tǒng)還希望能回 到當(dāng)初異常發(fā)生時(shí)被打斷的源程序斷點(diǎn)處繼續(xù)完成源程序的執(zhí)行(異常返回),這就需要一種解決方案, 用于記錄源程序的斷點(diǎn)位置,以便正確的異常返回。 類似的還有子程序的調(diào)用和 返回。在主程序中(通過子程序調(diào)用指令)調(diào)用子程序時(shí),也需要記錄下主程序中的調(diào)用點(diǎn)位置,以便將來的子程序的返回。
LR:鏈接寄存器(linked pointer),就是用來解決上述問題的,ARM處理器中使用 R14實(shí)現(xiàn)對斷點(diǎn)和調(diào)用點(diǎn)的記錄,即R14用作返回連接寄存器(LR),確?;貋碇雷约簭哪膫€(gè)位置中斷,以便繼續(xù)執(zhí)行.
在鴻蒙內(nèi)核R14是當(dāng)LR寄存器使用.
PC(R15) 寄存器
簡稱 PC(Program Counter)。當(dāng)執(zhí)行 ARM 指令(每條指令 4 字節(jié)),它的值為當(dāng)前指令的地址加 8,當(dāng)執(zhí)行 Thumb 指令事,它的值為當(dāng)前指令的地址加 4,其設(shè)計(jì)原則是讓 PC 指向當(dāng)前指令后面的第二條指令。
PC寄存器涉及到arm的流水線結(jié)構(gòu)設(shè)計(jì),具體在后續(xù)流水線篇中詳細(xì)說明,敬請關(guān)注.
在鴻蒙內(nèi)核R15是當(dāng)PC寄存器使用.
CPSR 寄存器
CPSR(current program status register)當(dāng)前程序的狀態(tài)寄存器 CPSR有4個(gè)8位區(qū)域:標(biāo)志域(F)、狀態(tài)域(S)、擴(kuò)展域(X)、控制域(C) 32 位的程序狀態(tài)寄存器可分為4 個(gè)域:
位[31:24]為條件標(biāo)志位域,用f 表示;
位[23:16]為狀態(tài)位域,用s 表示;
位[15:8]為擴(kuò)展位域,用x 表示;
位[7:0]為控制位域,用c 表示;
CPSR和其他寄存器不一樣,其他寄存器是用來存放數(shù)據(jù)的,都是整個(gè)寄存器具有一個(gè)含義. 而CPSR寄存器是按位起作用的,也就是說,它的每一位都有專門的含義,記錄特定的信息.
CPSR的低8位(包括I、F、T和M[4:0])稱為控制位,程序無法修改, 除非CPU運(yùn)行于特權(quán)模式下,程序才能修改控制位
N、Z、C、V均為條件碼標(biāo)志位。它們的內(nèi)容可被算術(shù)或邏輯運(yùn)算的結(jié)果所改變, 并且可以決定某條指令是否被執(zhí)行!意義重大!
CPSR的第31位是 N,符號標(biāo)志位。它記錄相關(guān)指令執(zhí)行后,其結(jié)果是否為負(fù). 如果為負(fù) N = 1,如果是非負(fù)數(shù) N = 0.
CPSR的第30位是Z,0標(biāo)志位。它記錄相關(guān)指令執(zhí)行后,其結(jié)果是否為0. 如果結(jié)果為0.那么Z = 1.如果結(jié)果不為0,那么Z = 0.
CPSR的第29位是C,進(jìn)位標(biāo)志位(Carry)。一般情況下,進(jìn)行無符號數(shù)的運(yùn)算。 加法運(yùn)算:當(dāng)運(yùn)算結(jié)果產(chǎn)生了進(jìn)位時(shí)(無符號數(shù)溢出),C=1,否則C=0。 減法運(yùn)算(包括CMP):當(dāng)運(yùn)算時(shí)產(chǎn)生了借位時(shí)(無符號數(shù)溢出),C=0,否則C=1。
CPSR的第28位是V,溢出標(biāo)志位(Overflow)。在進(jìn)行有符號數(shù)運(yùn)算的時(shí)候, 如果超過了機(jī)器所能標(biāo)識(shí)的范圍,稱為溢出。
MSR{條件} 程序狀態(tài)寄存器(CPSR 或SPSR)_<域>,操作數(shù) MSR 指令用于將操作數(shù)的內(nèi)容傳送到程序狀態(tài)寄存器的特定域中 示例如下:
MSR CPSR,R0 @傳送R0 的內(nèi)容到CPSR MSR SPSR,R0 @傳送R0 的內(nèi)容到SPSR MSR CPSR_c,R0 @傳送R0 的內(nèi)容到CPSR,但僅僅修改CPSR中的控制位域
MRS{條件} 通用寄存器,程序狀態(tài)寄存器(CPSR 或SPSR) MRS 指令用于將程序狀態(tài)寄存器的內(nèi)容傳送到通用寄存器中。該指令一般用在以下兩種情況: 1) 當(dāng)需要改變程序狀態(tài)寄存器的內(nèi)容時(shí),可用MRS 將程序狀態(tài)寄存器的內(nèi)容讀入通用寄存器,修改后再寫回程序狀態(tài)寄存器。 2) 當(dāng)在異常處理或進(jìn)程切換時(shí),需要保存程序狀態(tài)寄存器的值,可先用該指令讀出程序狀態(tài)寄存器的值,然后保存。 示例如下:
MRS R0,CPSR @傳送CPSR 的內(nèi)容到R0 MRS R0,SPSR @傳送SPSR 的內(nèi)容到R0 @MRS指令是唯一可以直接讀取CPSR和SPSR寄存器的指令
SPSR 寄存器
SPSR(saved program status register)程序狀態(tài)保存寄存器.五種異常模式下一個(gè)狀態(tài)寄存器SPSR,用于保存CPSR的狀態(tài),以便異常返回后恢復(fù)異常發(fā)生時(shí)的工作狀態(tài)。
1、SPSR 為 CPSR 中斷時(shí)刻的副本,退出中斷后,將SPSR中數(shù)據(jù)恢復(fù)到CPSR中。
2、用戶模式和系統(tǒng)模式下SPSR不可用,所以SPSR寄存器只有5個(gè)
編輯:hfy
-
ARM處理器
+關(guān)注
關(guān)注
6文章
360瀏覽量
41720 -
SIMD
+關(guān)注
關(guān)注
0文章
33瀏覽量
10289 -
狀態(tài)寄存器
+關(guān)注
關(guān)注
0文章
39瀏覽量
7081
發(fā)布評論請先 登錄
相關(guān)推薦
評論