百科詞條
狀態寄存器又名條件碼寄存器,它是計算機系統的核心部件——運算器的一部分,狀態寄存器用來存放兩類信息:一類是體現當前指令執行結果的各種狀態信息(條件碼),如有無進位(CF位)、有無溢出(OV位)、結果正負(SF位)、結果是否為零(ZF位)、奇偶標志位(P位)等;另一類是存放控制信息(PSW:程序狀態字寄存器),如允許中斷(IF位)、跟蹤標志(TF位)等。有些機器中將PSW稱為標志寄存器FR(Flag Register)。
CPSR
???CPU內部的寄存器中,有一種特殊的寄存器(對于不同的處理器,個數和結構都可能不同).這種寄存器在ARM中,被稱為狀態寄存器就是CPSR(current program status register)寄存器
CPSR和其他寄存器不一樣,其他寄存器是用來存放數據的,都是整個寄存器具有一個含義.而CPSR寄存器是按位起作用的,也就是說,它的每一位都有專門的含義,記錄特定的信息.
注:CPSR寄存器是32位的。我們可以通過修改 cpsr 寄存器的值來改變程序運行的結果。
(CPSR:8 個 16 進制位,1 個16進制位==4 個二進制位,所以為32個二進制位==4個 Byte)
如:
注: cpsr 的首位 8 二進制則為:1000,每一位的 0 和 1 都代表不同意義。通過修改為 0100,即:
查看執行結果:
但是我的依然沒改過來:???
- CPSR的低8位(包括I、F、T和M[4:0])稱為控制位,程序無法修改,除非CPU運行于特權模式下,程序才能修改控制位!
- N、Z、C、V均為條件碼標志位。它們的內容可被算術或邏輯運算的結果所改變,并且可以決定某條指令是否被執行!意義重大!~~~~
N(Negative)標志
CPSR的第31位是 N,符號標志位。它記錄相關指令執行后,其結果是否為負.如果為負 N = 1,如果是非負數 N = 0.
如:
Printing description of $cpsr:
(unsigned int) cpsr = 0x80000000
1000
(unsigned int) cpsr = 0x60000000
0100
nzcv
???注意,在ARM64的指令集中,有的指令的執行時影響狀態寄存器的,比如add\sub\or等,他們大都是運算指令(進行邏輯或算數運算);
Z(Zero)標志
CPSR的第30位是Z,0標志位。它記錄相關指令執行后, 判斷結果是否為0.如果結果為0.那么Z = 1.如果結果不為0,那么Z = 0.
???對于Z的值,我們可以這樣來看,Z標記相關指令的計算結果是否為0,如果為0,則N要記錄下"是0"這樣的肯定信息.在計算機中1表示邏輯真,表示肯定.所以當結果為0的時候Z = 1,表示"結果是0".如果結果不為0,則Z要記錄下"不是0"這樣的否定信息.在計算機中0表示邏輯假,表示否定,所以當結果不為0的時候Z = 0,表示"結果不為0"。
C(Carry)標志
CPSR的第29位是C,進位標志位。一般情況下,進行無符號數的運算。
加法運算:當運算結果產生了進位時(無符號數溢出),C=1,否則C=0。
減法運算(包括CMP):當運算時產生了借位時(無符號數溢出),C=0,否則C=1。
???對于位數為N的無符號數來說,其對應的二進制信息的最高位,即第N - 1位,就是它的最高有效位,而假想存在的第N位,就是相對于最高有效位的更高位。如下圖所示:
注:有符號/無符號,就是下面的,CPU在運算的時候,按位去運算的,并不丟棄這個進位制,而是記錄在一個特殊的寄存器的某一位上。這位有值就為負數,反之為正數。ARM下就用C位來記錄這個進位值。如果為純數字就是一個數字。
進位
???我們知道,當兩個數據相加的時候,有可能產生從最高有效位向更高位的進位。比如兩個32位數據:0xaaaaaaaa + 0xaaaaaaaa,將產生進位。由于這個進位值在32位中無法保存,我們就只是簡單的說這個進位值丟失了。其實CPU在運算的時候,并不丟棄這個進位制,而是記錄在一個特殊的寄存器的某一位上。ARM下就用C位來記錄這個進位值。比如,下面的指令
// C
// 加法 -- 進位
asm(
"mov w0,#0xaaaaaaaa\n"http://0xa 的二進制是 1010
"adds w0,w0,w0\n" // 執行后 相當于 1010 << 1 進位1(無符號溢出) 所以C標記 為 1
"adds w0,w0,w0\n"http:// 執行后 相當于 0101 << 1 進位0(無符號沒溢出) 所以C標記 為 0
"adds w0,w0,w0\n" // 重復上面操作
"adds w0,w0,w0\n"
);
借位
???當兩個數據做減法的時候,有可能向更高位借位。再比如,兩個32位數據:0x00000000 - 0x000000ff,將產生借位,借位后,相當于計算0x100000000 - 0x000000ff。得到0xffffff01 這個值。由于借了一位,所以C位 用來標記借位。C = 0.比如下面指令:
// 減法 -- 借位
mov w0,#0x0
subs w0,w0,#0xff ;
subs w0,w0,#0xff
subs w0,w0,#0xff
V(Overflow)溢出標志
1 代表溢出,0 未溢出。
CPSR的第28位是V,溢出標志位。在進行有符號數運算的時候,如果超過了機器所能標識的范圍,稱為溢出。(溢出不算進位)
- 正數 + 正數 為負數 溢出
- 負數 + 負數 為正數 溢出
- 正數 + 負數 不可能溢出
// V 溢出位
asm(
"mov w0, #0x7fffffff\n"
"adds w0, w0, #0xff2\n"
"mov w0, #0x80000000\n"
"subs w0,w0, #0x02\n"
);
結果
Printing description of $cpsr:
(unsigned int) cpsr = 0x30000000
0011
有點不太明白,一個最大的負數減去一個正數結果怎么變成一個正數了呢?溢出了
莫非是符號位不算?
小結:
N、Z、C、V
N
CPSR的第31位是 N,結果如果為負 N = 1,如果是非負數 N = 0.
Z
CPSR的第30位是Z,0標志位。如果結果為0.那么Z = 1.如果結果不為0,那么Z = 0.
C
CPSR的第29位是C,進位標志位。
加法運算:當運算結果產生了進位時(無符號數溢出),C=1,否則C=0。
減法運算(包括CMP):當運算時產生了借位時(無符號數溢出),C=0,否則C=1。
V
CPSR的第28位是V,溢出標志位。在進行有符號數運算的時候,如果超過了機器所能標識的范圍,稱為溢出。
1 代表溢出,0 未溢出。