彙編中,加法指令很重要,因為它是執行其他很多指令的基礎。
同時,加法指令也會影響NZCV
標誌。有關NZCV
的介紹,可以參看《一文搞懂 ARM 64 系列: ADC》。
ARM64
彙編中,ADD
指令有3
種形式,這裡介紹第一種形式,也就是與立即數
相加。
1 指令語法
ADD <Xd|SP>, <Xn|Sp>, #imm{, shift}
{}
裡的內容表示是可選的。
shift
表示LSL(邏輯左移)
的位數,有2
個取值,一個是0
,一個是12
。0
是其預設值。
所謂LSL(邏輯左移)
,是指將數值整體向左移動,低位補0
。如果高位被移出去,直接丟棄。
2 指令語義
整個指令就是將源暫存器<Xn|SP>
,與立即數imm
(如果有必要,需要進行LSL
)相加,將結果寫入目的暫存器<Xd|SP>
。
注意,這條指令不影響NZCV
標誌。
(<Xd|SP>, _) = <Xn|Sp> + imm << shift
3 NZCV 如何受影響
雖然這條指令最終不影響NZCV
標誌,但是搞清楚NZCV
如何受影響,還是很有必要的。
1
將源暫存器的值<Xn|SP>
和imm << shift
都當成無符號整型數
,兩數相加,得到一個無符號整型數
的結果,記作u_result
。此時計算時不考慮溢位:
<Xn|SP> = 0xffffffffffffffff // 64 bit 全 1
(imm << shift) = 1
u_result = 0xffffffffffffffff + 1 = 0x10000000000000000 // 2^64,而不是 0
2
將源暫存器的值<Xn|SP>
和imm << shift
都當成有符號整型數
,兩數相加,得到一個有符號整型數
的結果,記作s_result
。此時計算時不考慮溢位:
<Xn|SP> = 0xffffffffffffffff // 64 bit 全 1,此時當成 -1 看待
(imm << shift) = 0x8000000000000000 // 64 bit 最小負整數 -9223372036854775808
s_result = -1 + (-9223372036854775808) = -9223372036854775809 // 而不是 0x7fffffffffffffff
3
從u_result
中取(63~0)
共64bit
,記作result
;
4
如果result
的最高位是1
,那麼N = 1
;
5
如果result = 0
,那麼Z = 1
;
6
如果把result
當成無符號整型數
,它的值等於u_result
,那麼C = 0
;如果不等於,那麼C = 1
,也就是在進行加法運算時,發生了進位。
7
如果把result
當成有符號整型數
,它的值等於s_result
,那麼V = 0
;如果不等於,那麼V = 1
,也就是說在進行加法運算,發生了溢位。