在M68K中,有许多条件分支指令,和jmp指令一样也会修改PC达到程序跳转或分支的目的,不过这些会根据一些情况或状态来选择是否跳转。而在M68K中,有一个特别的寄存器来标记这些情况。
CCR(状态标志寄存器)
CCR寄存器是用来保存一些对应的状态数据,这些状态可以帮我们了解到比如:数据1和数据2是否相等,数据1是否大于数据2,数据值是否为负 等等情况。而保存这些状态的目的是可以让M68K程序能够在不同的状态下执行不同的动作。
ccr寄存器的大小为1个字节(8比特),我们在观察该寄存器时,通常是在二进制的状态下去观察,如:
- - - X N Z V C0 0 0 0 0 0 0 0
可以看到,m68k 有5个状态标志 (flag):X N Z V C,这五个状态分别有特殊的作用
C - Carry (进位)
V - oVerflow (溢出)
Z - Zero (零结果)
N - Negative (负结果)
X - eXtended (扩展)
进位(carry)
进位标志的作用就是比如当两个数据相加发生了进位时,该标志位会被设置为1:
addi.b #$05, d0
我们假设d0中的数据为$01,那么该指令的执行结果为$05 + $01 = $06,此时,并未发生进位,所以,在这状态下,进位标志位会被设为0。
那当我们假设d0中的数据为$FF,这时指令的执行结果为$05 + $FF = $104,这时,因为该指令的操作长度为单字节,所以这个结果只有$04会被保存到d0寄存器,而$104中的1因为超出了单字节范围,会被记录到进位标志位。此时,进位标志位会被设为1。
溢出(overflow)
要理解溢出,我们先要了解 无符号数 和 有符号数
无符号数:
在无符号数中,我们的数值没有正负的区别,所有数值都可以认为是正数,比如:
单字节长度:最小值为$00,最大值为$FF。
双字节长度:最小值为$0000,最大值为$FFFF。
四字节长度:最小值为$00000000,最大值为$FFFFFFFF。
而这些数,就是无符号数,就是从最小值到最大值的正数。
有符号数:
在有符号数中,我们在数值中加入了正负符号,比如:
单字节长度:$00-$7F为正数,$80-$FF为负数
双字节长度:$0000-$7FFF为正数,$8000-$FFFF为负数
四字节长度:$00000000-$7FFFFFFF,$80000000-$FFFFFFFF为负数
需要得到溢出状态,我们需要把数值当作有符号数,比如:当两个数值相加,得到的值为负数时的情况下就会把溢出状态标志设置为1。因为在数学上看来正数 + 正数 = 负数是不合逻辑的,所以M68K把这种情况解释为溢出。同样的情况还有比如负数 + 负数 = 正数,在这个状态下,也会把溢出状态标志设置为1。
零结果(Zero)
零结果比较容易理解,就是当计算的结果为零时,该状态标志就会被设置为1。
比如:
addi.b #$0,d0
如果d0 = $0,那么,计算的结果为$0 + $0 = $0,此时,该状态标志会被设置为1
subi.b #$5,d1
如果d1 = $5,计算的结果为 $5 - $5 = $0,此时,该状态标志会被设置为1
负结果 (Negative)
该状态也十分容易理解,就是当计算结果为负时,该状态标志就会被设置为1
扩展 (Extended)
该标志位和进位 (C) 状态标志一样,它会在进位发生的时候也被设置,并不是所有的修改进位状态标志的指令都会修改扩展状态标志,当你使用一条同时修改进位和扩展状态标志的指令之后,再去使用一条只会修改进位状态标志的指令,这时扩展 (X) 状态标志就会保留之前的那次进位的状态。
我们需要知道,并非用于计算的指令才能改变CCR寄存器,在M68K中,大部份指令都可以改变CCR状态,我们可以在指令说明中看到该指令可以改变哪些标志位状态。比如:
MOVE Move Data from Source to Destination 传递数据(原操作数->目的操作数)
运算: 原操作数 置入 目的操作数
语法: MOVE <ea>,<ea>
操作数长度:B、W、L
条件码(标志位): X — 不受影响。
N — 如果结果为负数则置1;其它情况置0。
Z — 如果结果为零则置1;其它情况置0。
V — 置0。
C — 置0。
可以看到move这个指令可以在什么情况下对哪些标志位产生影响。