状态寄存器 CPSR
CPU内部的寄存器中,有一种特殊的寄存器(对于不同的处理器,个数和结构都可能不同).这种寄存器在ARM中,被称为状态寄存器
就是CPSR(current program status register)寄存器
CPSR和其他寄存器不一样,其他寄存器是用来存放数据的,都是整个寄存器具有一个含义
.而CPSR寄存器是按位
起作用的,也就是说,它的每一位都有专门的含义,记录特定的信息
.
注意:状态寄存器是32位的
状态寄存器各bit的意义如下:
![](https://img.haomeiwen.com/i20589734/c108880d86d8afab.png)
- 31:
N(Negative)
标志 - 30:
Z(Zero)
标志 - 29:
C(Carry)
标志 - 28:
V(Overflow)
标志 - 8-27:保留位
- 0-7:低8位(包括I、F、T和M[4:0])称为
控制位
,程序无法修改
,除非CPU运行于特权模式下,程序才能修改控制位!
注意:N、Z、C、V均为条件码标志位
。它们的内容可被算术或逻辑运算
的结果所改变,并且可以决定某条指令是否被执行!意义重大!
N(Negative) 标志
它记录相关指令执行后,其结果是否为负。
* 结果为负数
,则N = 1
* 结果为非负数
,则N = 0
例如:当计算1-4 = -3
时,N标志
位则为1
。
在代码运行过程中查看一下寄存器的情况。
//假设有如下一段汇编
test_1`funA:
-> 0x104b1e1cc <+0>: mov w0, #0x7fffffff
0x104b1e1d0 <+4>: adds w0, w0, #0x1 ; =0x1
0x104b1e1d4 <+8>: subs w0, w0, #0x1 ; =0x1
0x104b1e1d8 <+12>: ret
//【1】w0被赋值为0x7FFFFFFF,此时的cpsr的值为:
(lldb) register read cpsr
cpsr = 0x60000000 <==> 0b01100000000000000000000000000000
//【2】将w0 = w0+0x01 = 0x80000000后,得到的cpsr的值为:
(lldb) register read cpsr
cpsr = 0x90000000 <==> 0b10010000000000000000000000000000
//【3】将w0 = w0-0x01 = 0x7FFFFFFF,此时的cpsr的值为:
(lldb) register read cpsr
cpsr = 0x30000000 <==> 0b00110000000000000000000000000000
注:adds
:做加法
的同时,修改状态寄存器(CPSR)
;subs
:做减法
的同时,修改状态寄存器(CPSR)
;
总结:
- W0是
四字节
大小,其最高位为符号位。符号位为1
:表示负数
;符号位为0
:表示正数
。 - 当0x7FFFFFFF+0x01=0x80000000,这表示结果为
负数
,此时CPSR寄存器的N标志位
变成1
。 - 当0x80000000-0x01=0x7FFFFFFF,这表示结果为
正数
,此时CPSR寄存器的N标志位
变成0
。
Z(Zero) 标志
它记录相关指令执行后,其结果是否为0.
- 结果为
0
,则Z = 1
- 结果为
非0
,那么Z = 0
例如:当计算1-1=0
时,Z标志
位就为1
。
//假设有如下一段汇编
test_1`funA:
-> 0x102ef21cc <+0>: mov w0, #0x0
0x102ef21d0 <+4>: adds w0, w0, #0x1 ; =0x1
0x102ef21d4 <+8>: subs w0, w0, #0x1 ; =0x1
0x102ef21d8 <+12>: ret
//【1】w0被赋值为0x0,此时的cpsr的值为:
(lldb) register read cpsr
cpsr = 0x60000000 <==> 0b01100000000000000000000000000000
//【2】将w0 = w0+0x01 = 0x01后,得到的cpsr的值为:
(lldb) register read cpsr
cpsr = 0x00000000 <==> 0b00000000000000000000000000000000
//【3】将w0 = w0-0x01 = 0x0,此时的cpsr的值为:
(lldb) register read cpsr
cpsr = 0x60000000 <==> 0b01100000000000000000000000000000
总结:
- 当0x0+0x01 = 0x01,此时结果为
非0
,CPSR寄存器的Z标志位
为0
。 - 当0x1-0x01 = 0x00,此时结果为
0
,CPSR寄存器的Z标志位
为1
。
C(Carry)标志
CPSR的第29位是C进位标志位
。一般情况下,进行无符号数的运算
。
加法运算
:当运算结果产生了进位(无符号数溢出)
时,C=1
,否则C=0
。
减法运算
:当运算时产生了借位(无符号数溢出)
时,C=0
,否则C=1
。
//假如有如下一段汇编
test_1`funA:
-> 0x10081e1bc <+0>: mov w0, #-0xFFFFFFFE
0x10081e1c0 <+4>: mov w1, #0x1
0x10081e1c4 <+8>: adds w0, w0, w1
0x10081e1c8 <+12>: adds w0, w0, w1
0x10081e1cc <+16>: mov w0, #0x1
0x10081e1d0 <+20>: subs w0, w0, w1
0x10081e1d4 <+24>: subs w0, w0, w1
0x10081e1d8 <+28>: ret
//当对w0和w1进行赋值时,CPSR寄存器的值为:
(lldb) register read cpsr
cpsr = 0x60000000 <==> 0b01100000000000000000000000000000
//【1】当0xFFFFFFFE+0x01=0xFFFFFFFF时,此时未产生进位。当前CPSR寄存器的值为:
(lldb) register read cpsr
cpsr = 0x80000000 <==> 0b10000000000000000000000000000000
//【2】当0xFFFFFFFF+0x01时,此时产生进位导致w0发生溢出。当前CPSR寄存器的值为:
(lldb) register read cpsr
cpsr = 0x60000000 <==> 0b01100000000000000000000000000000
//【3】当0x01-0x01时,此时不需要进行借位,当前CPSR寄存器的值为:
(lldb) register read cpsr
cpsr = 0x60000000 <==> 0b01100000000000000000000000000000
//【4】当0x0-0x01时,此时需要借位,当前CPSR寄存器的值为:
(lldb) register read cpsr
cpsr = 0x80000000 <==> 0b10000000000000000000000000000000
总结:
-
加法运算
:- 有进位,C=1
- 没有进位,C=0
-
减法运算
:- 有借位,C=0
- 没有借位,C=1
V(Overflow)溢出标志
CPSR的第28位是V溢出标志位
。在进行有符号数
运算的时候,如果超过了机器所能标识的范围
,称为溢出
。
//假如有如下一段汇编
test_1`funA:
-> 0x1007ee234 <+0>: mov w0, #0x7fffffff
0x1007ee238 <+4>: adds w0, w0, w0
0x1007ee23c <+8>: mov w0, #0x7fffffff
0x1007ee240 <+12>: mov w1, #-0x80000000
0x1007ee244 <+16>: adds w0, w1, w0
0x1007ee248 <+20>: mov w0, #-0x80000000
0x1007ee24c <+24>: adds w0, w0, w0
0x1007ee250 <+28>: ret
//当对w0进行赋值时,CPSR寄存器的值为:
(lldb) register read cpsr
cpsr = 0x60000000 <==> 0b01100000000000000000000000000000
//【1】当0x7FFFFFFF+0x7FFFFFFF=0xFFFFFFFE时,此时正数+正数,且超过正数最大标识,发生溢出。当前CPSR寄存器的值为:
(lldb) register read cpsr
cpsr = 0x90000000 <==> 0b10010000000000000000000000000000
//【2】当0x7FFFFFFE+0x80000000时,此时正数+负数,未发生溢出。当前CPSR寄存器的值为:
(lldb) register read cpsr
cpsr = 0x80000000 <==> 0b10000000000000000000000000000000
//【3】当0x80000000+0x80000000时,此时负数+负数,且超过负数的最大标识,发生溢出,当前CPSR寄存器的值为:
(lldb) register read cpsr
cpsr = 0x70000000 <==> 0b01110000000000000000000000000000
总结:
-
正数 + 正数
结果为负数
时,发生溢出
,V标志为1
-
负数 + 负数
结果为正数
时,发生溢出
,V标志为1
-
正数 + 负数
不可能发生溢出,V标志为0
。
网友评论