最近的文章可能會有較多修改,請關注博客哦
異常級別
ARMv8處理器支持4種異常等級(Exception Level,EL)。
-
EL0 為非特權模式,用于運行應用程序,其他資源訪問受限,權限不夠。
-
EL1 為特權模式,用于操作系統內核,可以訪問系統的所有資源
-
EL2 用于運行虛擬化管理管理程序(hypervisor)。
-
EL3 用于運行安全世界中的管理程序,安全模式(secure monitor)。
這里的異常概念不同于程序中的異常概念。當作中斷理解會好點。
執行狀態
ARMv8 架構定義了兩種執行狀態, AArch64和AArch32。當處于 AArch64 狀態時,處理器執行 A64 指令集。當處于 AArch32 狀態時,處理器可以執行 A32(在早期版本的架構中稱為 ARM)或 T32 (Thumb) 指令集。所以,ARMv8的設備可以運行老程序,它是向前兼容的。
注意,AArch64 OS 運行 AArch32 程序時,當應用程序調用(SVC)指令,或接收中斷,會切換到 EL1 和 AArch64。
寄存器
AArch64執行狀態提供了32個在任何時間任何特權級下都可訪問的64位的通用寄存器。
每個寄存器都有64位寬,它們通常被稱為寄存器X0-X30。
每個AArch64 64位通用寄存器(X0-X30)也具有32位(W0-W30)形式。
也就是說,64位模式下寄存器名字叫 Xn,32位模式下名字叫 Wn。這些東西與 CSAPP 里面講的都是差不多的,只不過它講的是 X86 架構。
每個寄存器的用途如下:
在aarch64中,沒有x31或w31寄存器,但是在一些指令或軟件編碼中,經常將數字31作為XZR或SP
-
X0-X7:用于參數傳遞
-
X9-X15:調用方需要保存這些寄存器的值,因為被調用函數可能會修改這些寄存器。
-
X19-X29:被調用方保存這些寄存器的值,退出時再恢復,因為函數返回后可能調用方還會用到這些寄存器的值。
-
X8, X16-X18, X29, X30:這些都是特殊用途的寄存器
特殊寄存器
-
X8:?用于儲存間接結果的寄存器,比如返回一個結構體的時候,該寄存器儲存的是結構體地址。
-
X18:不管
-
sp:保存棧頂地址
-
fp:保存棧底地址
-
lr:保存調用跳轉指令?
bl
?指令的下一條指令的內存地址 -
zr:
xzr/wzr
分別代表 64/32 位,可用于清零的操作,零寄存器 -
pc:?保存將要執行的指令的地址
PSTATE
程序狀態寄存器,程序中會存在很多分支,具體走哪條分支,是由狀態寄存器決定的,比如一些比較指令執行時,需要根據狀態寄存器的負數標志來決定是否進行邏輯分支跳轉。
在aarch64中,只能可以通過MSR/MRS指令訪問特殊寄存器(special-purpose)的方式讀寫這些位。除了這些特殊寄存器中表示的位,PSTATE的其它位都是不能訪問的。
指令格式
ARM指令的基本格式如下:
<opcode> {<cond>} {S} <Rd>, <Rn>{,<operand2>}
其中<>號內的項是必須的,{}號內的項是可選的。各項的說明如下:
-
opcode:指令助記符
-
cond:執行條件
-
S:是否影響CPSR寄存器的值
-
Rd:目標寄存器
-
Rn:第一個操作數的寄存器
-
operand2:第2個操作數
ARM指令格式舉例:
-
LDR R0, [R1]:讀取R1地址上的存儲單元內容,執行條件AL;
-
BEQ DATAEVEN:條件執行分支指令,執行條件EQ,即相等則跳轉到DATAEVEN;
-
ADDS R2, R1, #1:加法指令,R2<-R1+1,影響CPSR寄存器;
-
SUBNES R2, R1,#0x20:條件執行的減法運算,執行條件NE,R1-0x20->R2,影響CPSR寄存器
AArch64沒有直接與ARMv7中的CPSR等價的寄存器,但是可以訪問PSTATE中對應的字段。
尋址方式
我覺的 csapp 在這方面講的是真的好,一個表格就讓初學者對匯編了解很多。看一個例子:
這個表格就說清楚了各種尋址方式對應的匯編格式。
我們看看 arm64 的尋址方式。
立即尋址
立即尋址也叫立即數尋址,這是一種特殊的尋址方式,操作數本身就在指令中給出,只要取出指令也就取到了操作數,這個操作數被稱為立即數,對應的方式也稱為立即尋址
ADD W0, W1, *#0x05*
寄存器尋址
寄存器尋址也就是利用寄存器中的數值作為操作數,這是一種常見的方式,也是效率比較高的尋址方式
ADD W0, W1, W2
寄存器間接尋址
寄存器間接尋址就是以寄存器中值作為操作數的地址,而操作數本身存放在存儲器中
ADD W0, W1, [W2]
LDR W3, [W0]
基址變址尋址
基址變址尋址就是將寄存器(該寄存器一般稱作基址寄存器)的內容與指令中給出的地址偏移量相加,從而得到一個操作數的有效地址。變址尋址方式常用于訪問某基地址附近的地址單元, 常見的有以下幾種形式:
LDR W0, [W1, #4] ;將寄存器w1中內容加上4作為地址,然后將該地址處的數據存入寄存器w0中
LDR W0, [W1, #4]! ;將寄存器w1中內容加上4作為地址,然后將該地址處的數據存入寄存器w0中,然后w1中的內容自增4
LDR W0, [W1], #4 ;將寄存器w1中的內容作為地址,然后將該地址處的數據存入w0中,并將w1中內容自增4
LDR W0, [W1, W2] ;將w1和w2中的內容相加作為地址,然后將該地址處的數據存入w0
后綴
上面有個例子:
LDR W0, [W1, #4]!
匯編后面有個感嘆號。ARM中的指令可以帶后綴,從而豐富該指令的功能,常用的后綴有:
位數后綴
B(byte):功能不變,操作長度變為8位(依賴CPU位數,以下相同)?
H(Halfword):功能不變,操作長度變為16位
例如:ldr指令族:ldrb,ldrh,ldrsb ldrsh,從內存中加載指定長度的數據
S后綴
影響CPSR里的NZCV標識位。指令中使用”S“后綴時、指令執行后程序狀態寄存器的條件標志位將被刷新。相當于有符號運算。
例如:
SUB X1,X0,X3 ;X1=X0-X3 ,CPSR值不變
SUBS X1,X0,X3 ;X1=X0-X3 , 如果計算結果為負數,CPSR寄存器的N被置位
! 后綴
指令中地址表達式含有“!”后綴時,指令執行后,基址寄存器中的地址值將會發生變化。變化的結果是 (base+offset)。
例如:
LDR X3,[X0,#4] //X3=X0+4
LDR X3,[X0,#4]! //X3=X0+4; X0+=4;
注意:“!”不能用于寄存器PC后面
條件后綴
ARM架構中,允許在指令后面添加條件后綴來完成指令條件執行的目的。指令條件執行就是說,指令根據CPSR中條件碼的狀態和指令的條件域有條件的執行。當指令的執行條件滿足時,指令被執行,否則指令將被忽略。
例如:
ADD X4,X2,#1 ; 無條件執行 X4=X2+1
ADDEQ X4,X2,#1 ;添加有條件執行后綴EQ,當CPSR中的Z標志置位(之前某條CMP結果相等)時,該指令才執行。注意:如果條件后綴和“S”標識同時出現,則S在條件后綴的后面,例如:
ADDEQS X4,X2,#1 ;即為有條件執行X4=X2+1,結果更新條件標志位