汇编六、状态寄存器

CPU内部的寄存器中,有一种特殊的寄存器,这种寄存器在ARM中,被称为状态寄存器,即CPSR(current program satus register)寄存器;
CPSR和其他寄存器不一样,其他寄存器是用来存放数据的,都是一个寄存器具有一个含义。而CPSR寄存器是按位起作用的,也就是说,它的每一位都具有专门的含义,用来记录特定的信息;

注:CPSR寄存器是32位的;

  • CPSR的低8位(包括I、F、T和M[4: 0])称为控制位,程序无法修改,除非CPU运行于特权模式下,程序才能修改控制位。
  • N、Z、C、V均为条件标志位。他们的内容可以被算数运算(加减乘除)或逻辑运算(if判断)的结果所修改,并且可以决定某条指令是否被执行。意义重大!!!


N(Negative)标志

  • CPSR的第31位是N,符号标志位。
  • 它记录了某条指令执行的结果是否为负;如果为负的,则N=1;如果为非负的,则N=0;

把执行结果当做有符号数据,那么N就是该数据的符号位(1代表负数,0代表非负数)

mov x0 #0x0fffffff
adds w0 w0 #0x1 
;命令执行后,执行结果为0x10000000, N = 1

Z(Zero)标志

  • CPSR的第30位是Z,0标志位;
  • 它记录了某条指令执行的结果是否为0;如果为0,则Z=1;如果不为0,则Z=0;
mov x0 #0x0
adds w0 w0 #0x0
;命令执行后,结果为0x0, Z=1

C(Carry)标志

  • CPSR的第29位是C,进位标志;一般情况下,进行无符号数的运算;
  • 加法运算:当运算结果产生了进位时(无符号数溢出),C=1;否则C=0;
  • 减法运算(包括CMP):当运算结果产生了借位时(无符号数溢出),则C=0,否则C=1;

C标志用来记录算数运算时,产生的无符号溢出的那一位;
加法运算:两个8位数相加,如果产生进位,进位为1,则C为1;如果没有产生进位,进位则为0,则C为0;
减法运算:A减去B,如果A比B小,则要向前借一位,则C为0;如果A比B大,则不需要借位,则C为1;

进位

当两个数相加的时候,有可能产生从最高位向前进一位;比如两个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位V,溢出标志位;
  • 在进行有符号运算的时候,如果超出了机器所能标示的范围,称为溢出

正数 + 正数 = 负数 => 溢出

9 + 5 = 14没溢出01001 + 00101 = 01110
12 + 7 = 19 溢出 01100 + 00111 = 10011

负数 + 负数 = 正数 => 溢出

(-9) + (-5) = (-14) 没溢出 11001 + 11011 = 110010
(-12)+(-7)=-19 溢出 10100+11001=101101

正数 + 负数 !=> 溢出

你可能感兴趣的:(汇编六、状态寄存器)