14.2異常與中斷_CPU模式(Mode)_狀態(tài)(State)與寄存器
這節(jié)課我們來講CPU的工作模式(Mode) 狀態(tài)(State)寄存器
7種Mode:?
usr/sys?
undefined(und)?
Supervisor(svc)?
Abort(abt)?
IRQ(irq)?
FIQ(fiq)
2種State:?
ARM state?
Thumb state
寄存器:?
通用寄存器
備份寄存器(banked register)
當(dāng)前程序狀態(tài)寄存器(Current Program Status Register);CPSR
CPSR的備份寄存器:SPSR(Save Program Status Register)
我們?nèi)匀灰赃@個(gè)母親為例講解這個(gè)CPU模式 這個(gè)母親無壓力看書 -->(正常模式) 要考試,看書--->(興奮模式) 生病---->(異常模式)
可以參考書籍 《ARM體系結(jié)構(gòu)與編程》作者:杜春雷
對(duì)于ARM CPU有7種模式:
1 usr :類比 正常模式
2 sys :類比的話興奮模式
3 5種異常模式:(2440用戶手冊(cè)72頁)
3.1 und :未定義模式
3.2 svc :管理模式
3.3 abt :終止模式
a 指令預(yù)取終止(讀寫某條錯(cuò)誤的指令導(dǎo)致終止運(yùn)行)
b 數(shù)據(jù)訪問終止 (讀寫某個(gè)地址,這個(gè)過程出錯(cuò))
都會(huì)進(jìn)入終止模式
3.4 IRQ: 中斷模式
3.5 FIQ: 快中斷模式
我們可以稱以下6種為特權(quán)模式?
und :未定義模式
svc :管理模式
abt :終止模式
IRQ :中斷模式
FIQ :快中斷模式
sys :系統(tǒng)模式
usr用戶模式(不可直接進(jìn)入其他模式) ?可以編程操作CPSR直接進(jìn)入其他模式

這個(gè)圖是有關(guān)各個(gè)模式下能訪問寄存器的,再講這個(gè)圖之前我們先引入 2種state
CPU有兩種state:
1 ARM state:使用ARM指令集,每個(gè)指令4byte
2 Thumb state:使用的是Thumb指令集,每個(gè)指令2byte
比如同樣是:
mov R0, R1 編譯后
對(duì)于ARM指令集要占據(jù)4個(gè)字節(jié):機(jī)器碼
對(duì)于Thumb指令集占據(jù)2個(gè)字節(jié):機(jī)器碼
引入Thumb減少存儲(chǔ)空間
ARM指令集與Thumb指令集的區(qū)別:
Thumb 指令可以看作是 ARM 指令壓縮形式的子集,是針對(duì)代碼密度的問題而提出的,它具有 16 位的代碼密度但是它不如ARM指令的效率高 .
Thumb 不是一個(gè)完整的體系結(jié)構(gòu),不能指望處理只執(zhí)行Thumb 指令而不支持 ARM 指令集.
因此,Thumb 指令只需要支持通用功能,必要時(shí)可以借助于完善的 ARM 指令集,比如,所有異常自動(dòng)進(jìn)入 ARM 狀態(tài).在編寫 Thumb 指令時(shí),先要使用偽指令 CODE16 聲明,而且在 ARM 指令中要使用 BX指令跳轉(zhuǎn)到 Thumb 指令,以切換處理器狀態(tài).編寫 ARM 指令時(shí),則可使用偽指令 CODE32聲明.
下節(jié)課會(huì)演示使用Thumb指令集編譯,看是否生成的bin文件會(huì)變小很多

在每種模式下都有R0 ~ R15
在這張圖注意到有些寄存器畫有灰色的三角形,表示訪問該模式下訪問的專屬寄存器 比如?

在System 模式下訪問的是R0 ~ R8,在所有模式下訪問R0都是同一個(gè)寄存器?
mov R0,R8_fiq
但是在FIQ模式下,訪問R8是訪問的FIQ模式專屬的R8寄存器,不是同一個(gè)物理上的寄存器
在這五種異常模式中每個(gè)模式都有自己專屬的R13 R14寄存器,R13用作SP(棧) R14用作LR(返回地址) LR是用來保存發(fā)生異常時(shí)的指令地址
為什么快中斷(FIQ)有那么多專屬寄存器,這些寄存器稱為備份寄存器
回顧一下中斷的處理過程
1 保存現(xiàn)場(chǎng)(保存被中斷模式的寄存器)
就比如說我們的程序正在系統(tǒng)模式/用戶模式下運(yùn)行,當(dāng)你發(fā)生中斷時(shí),需要把R0 ~ R14這些寄存器全部保存下來,讓后處理異常,最后恢復(fù)這些寄存器
但如果是快中斷,那么我就不需要保存 系統(tǒng)/用戶模式下的R8 ~ R12這幾個(gè)寄存器,在FIQ模式下有自己專屬的R8 ~ R12寄存器,省略保存寄存器的時(shí)間,加快處理速度
但是在Linux中并不會(huì)使用FIQ模式
2 處理
3 恢復(fù)現(xiàn)場(chǎng)
CRSR當(dāng)前程序狀態(tài)寄存器,這是一個(gè)特別重要的寄存器
SPSR保存的程序狀態(tài)寄存器,他們格式如下:

首先 M4 ~ M0 表示當(dāng)前CPU處于哪一種模式(Mode);
我們可以讀取這5位來判斷CPU處于哪一種模式,也可以修改這一種模式位,讓其修改這種模式;
假如你當(dāng)前處于用戶模式下,是沒有權(quán)限修改這些位的;
M4 ~ M0對(duì)應(yīng)什么值,會(huì)有說明:

查看其他位?
Bit5 State bits表示CPU工作與Thumb State還是ARM State用的指令集是什么
Bit6 FIQ disable當(dāng)bit6等于1時(shí),F(xiàn)IQ是不工作的
Bit7 IRQ disable當(dāng)bit5等于1時(shí),禁止所有的IRQ中斷,這個(gè)位是IRQ的總開關(guān)
Bit8 ~ Bit27是保留位
Bite28 ~ Bit31是狀態(tài)位,
什么是狀態(tài)位,比如說執(zhí)行一條指令?
cmp R0, R1
如果R0 等于 R1 那么zero位等于1,這條指令影響 Z 位,如果R0 == ?R1,則Z = 1
beq跳轉(zhuǎn)到xxx這條指令會(huì)判斷Bit30是否為1,是1的話則跳轉(zhuǎn),不是1的話則不會(huì)跳轉(zhuǎn) 使用 Z 位,如果 Z 位等于1 則跳轉(zhuǎn),這些指令是借助狀態(tài)位實(shí)現(xiàn)的
SPSR保存的程序狀態(tài)寄存器:
表示發(fā)生異常時(shí)這個(gè)寄存器會(huì)用來保存被中斷的模式下他的CPSR
就比如我我的程序在系統(tǒng)模式下運(yùn)行 CPSR是某個(gè)值,當(dāng)發(fā)生中斷時(shí)會(huì)進(jìn)入irq模式,這個(gè)CPSR_irq就保存系統(tǒng)模式下的CPSR
我們來看看發(fā)生異常時(shí)CPU是如何協(xié)同工作的:
進(jìn)入異常的處理流程(硬件)

我們來翻譯一下:
發(fā)生異常時(shí),我們的CPU會(huì)做什么事情
1把下一條指令的地址保存在LR寄存器里(某種異常模式的LR等于被中斷的下一條指令的地址)
它有可能是PC + 4有可能是PC + 8,到底是那種取決于不同的情況
2 把CPSR保存在SPSR里面(某一種異常模式下SPSR里面的值等于CPSR)
3 修改CPSR的模式為進(jìn)入異常模式(修改CPSR的M4 ~ M0進(jìn)入異常模式)
4 跳到向量表
退出異常怎么做?

1 讓LR減去某個(gè)值,讓后賦值給PC(PC = 某個(gè)異常LR寄存器減去 offset)
減去什么值呢?
也就是我們?cè)趺捶祷厝ダ^續(xù)執(zhí)行原來的程序,根據(jù)下面這個(gè)表來取值

如果發(fā)生的是SWI可以把 R14_svc復(fù)制給PC
如果發(fā)生的是IRQ可以把R14_irq的值減去4賦值給PC
2 把CPSR的值恢復(fù)(CPSR 值等于 某一個(gè)一場(chǎng)模式下的SPSR)
3 清中斷(如果是中斷的話,對(duì)于其他異常不用設(shè)置)