状态寄存器
CPU内部的寄存器中, 有一种特殊的寄存器(不同的处理器, 结构和寄存器个数都可能不同). 这种寄存器在ARM中, 称为 CPSR (current program status register) 状态寄存器.
CPSR和其他寄存器不一样, 其他寄存器都是用来存放数据的, 一个寄存器对应一个含义 ; 而CPSR寄存器是按位起作用的, 每一位都有专门的含义,记录特定的信息.
注意: CPSR 寄存器是32位的
CPSR的低8位(包括 I , F, T 和 M[4-0])称为控制位, 程序无法修改, 除非CPU运行于特权模式下, 才能修改控制位.
N Z C V均为条件码标志位, 它们的内容可被算术或逻辑运算的结果所改变, 并且决定某条指令是否被执行, 意义重大!
N (negative) 标志
CPSR 第31位是N, 符号标志位. 它记录相关指令执行后, 其结果是否为负, 如果为负,则 N 为1; 如果非负则N为0.
- 在ARM64指令集中, 有些指令的执行是影响状态寄存器的. 比如 add/sub/or等, 它们大都是运算指令(进行逻辑或算术运算).
Z (zero) 标志
CPSR 第30位是Z, 0标志位. 它记录相关指令执行后, 其结果是否为0, 如果为0,则Z为1; 如果非0则Z为0.
C (carry) 标志
CPSR 第29位是C, 进位标志位. 一般情况下, 进行无符号的运算.
加法运算: 当运算结果产生了进位时(无符号位溢出), 则 C = 1, 否则C=0.
减法运算(包括CMP): 当运算结果产生了借位时(无符号数溢出), 则C=0,否则C=1.
对于位数为N的无符号数来说,其对应的二进制信息的最高位,即第N - 1位,就是它的最高有效位,而假想存在的第N位,就是相对于最高有效位的更高位。如下图所示:
进位
- 当两个数据相加的时候,有可能产生从最高有效位想更高位的进位。比如两个32位数据:0xaaaaaaaa + 0xaaaaaaaa,将产生进位。由于这个进位值在32位中无法保存,我们就只是简单的说这个进位值丢失了。其实CPU在运算的时候,并不丢弃这个进位制,而是记录在一个特殊的寄存器的某一位上。ARM下就用C位来记录这个进位值。比如,下面的指令
mov w0,#0xaaaaaaaa;0xa 的二进制是 1010
adds w0,w0,w0; 执行后 相当于 1010 << 1 进位1(无符号溢出) 所以C标记 为 1
adds w0,w0,w0; 执行后 相当于 0101 << 1 进位0(无符号没溢出) 所以C标记 为 0
adds w0,w0,w0; 重复上面操作
adds w0,w0,w0
借位
- 当两个数据做减法的时候,有可能向更高位借位。再比如,两个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)溢出标志
CPSR的第28位, 溢出标志位. 在进行有符号数运算的时候, 如果超出了机器所能识别的范围, 称为溢出.
- 正数 + 正数 为 负数, 溢出
- 负数 + 负数 为 正数, 溢出
- 正数 + 负数 不可能溢出
第四篇对于初识汇编的复习和梳理就到这了