关于OF和CF

    很久很久前写的。越来越意识到作为一名科班出身的学生的重要性。

    自己在使用IDA时,发现F5产生类似的这种代码。

    其中有一句,v5 <= -141920797,我在想为什么是负数。如果把-141920797化为16进制,如下图:

    为什么不是比较的无符号数0xab3f35e3?

    看一下对应的汇编代码,如下图:

    那么什么是BGT呢?在ARM指令中,有BGT和BHI,感觉都是"大于时跳转"的意思啊,区别在哪里呢?BGT是有符号比较分支指令,BHI是无符号比较分支指令。因此,IDA的F5会将0xab3f35e3当作有符号数来显示。

    顺便说一下汇编指令是根据什么判断结果呢?当然是根据N,Z,C,V这些符号标志了。那么什么情况下BGT会跳转呢?如果Z+(N^V)==0,那么就BGT就会跳转。

    那么这个Z+(N^V)该怎么理解呢?N就是Negative的意思,如果两个数运算结果的最高位是1,那么就将Negative置为1. V 是Overflow的意思,如果两个数运算结果发生了溢出,那么就会将V置为1.

CPU如何判断是否将V置为1呢?这就涉及到了CPU的溢出判断,CPU的溢出判断不是像我们通过手算判断出运算结果是否超出能表示的范围来判断溢出的。

    首先要标明的是,CPU里只有加法器而没有减法器,你看到的SUB指令,CMP指令看似是减法,到CPU里其实做的还是加法运算。使用如下的公式:

    [A+B]补 = [A]补 + [B]补

    [A-B]补 = [A]补 + [-B]补

    [-B]补由[B]的补连同符号位在内,每位取反,末位加1可得。

    定点补码运算判断溢出有两种方法,包括由一位符号位判断溢出和由两位符号位判断溢出。我在这里讲一下使用一位符号为判断溢出。结论如下:

    由于减法运算在机器中是用加法器实现的,因此可以得出如下结论:不论是作加法还是作减法,只要实际参加操作的两个数(减法时即为被减数和"求补"以后的减数)符号相同,结果又与原操作数符号不同,即为溢出。事实上,CPU也就是这么做的。

    到了现在,我们再来理一下为什么Z+(N^V)==0,那么就BGT就会跳转。当N=0,V=0,也就是运算的结果是非负数并且没有溢出,这个时候如果Z=0,那么结果就是正数,BGT就会跳转。当N=1,V=1也就是运算的结果是负数而且发生了溢出,既然发生了溢出,那么运算的结果应该是非负数,而非N=1表示的负数,这个时候如果Z=0,那么结果就是正数,BGT就会跳转。其他的情况也是类似的,在这里不再分析。

    顺便说下Carry flag,这个flag有点特殊,在不同的处理器家族中有不同的处理方法。在x86的处理器中,如果是加法指令而且发生了进位,则设Carray flag为1,否则设为0;如果是减法指令,刚才说过了减法指令做的还是加法运算,这个时候发生了进位却将Carray flag设置为0,否则设置为1。在StackOverflow上有关于这的一个讨论。

    http://stackoverflow.com/questions/12237725/carray-flag-in-substraction/

 

转载于:https://www.cnblogs.com/wangaohui/p/5186219.html

### 加法器中 OF CF 标志位的定义及区别 #### 1. **进位标志 (CF)** 进位标志(Carry Flag, CF)主要用于反映无符号数运算的结果是否产生了进位或借位。在加法操作中,当最高有效位(对于字节运算是第7位,对于字运算则是第15位等)产生进位时,CF会被置为1;而在减法操作中,如果最高有效位需要向更高位借位,则CF同样被置为1[^3]。 例如,在8位无符号数加法运算中,计算`255 + 1`(即二进制`11111111 + 00000001`),结果超出8位表示范围并产生进位,此时`CF = 1`。相反,如果没有进位或借位发生,则`CF = 0`。 #### 2. **溢出标志 (OF)** 溢出标志(Overflow Flag, OF)则专门用于检测有符号数运算过程中是否存在溢出情况。其核心在于判断运算结果是否超出了目标数据类型的取值范围。具体而言: - 对于两个带符号整数相加的情况,仅当两数同号且结果符号与原数不同(即发生了错误的符号翻转)时,OF才被置为1。 - 如果参与运算的两个数异号或者结果未超出范围,则不会触发OF。 举例说明:假设采用8位有符号整数进行如下运算: - `127 + 1`(即二进制`01111111 + 00000001`),理论上应得到`128`,但由于8位有符号数的最大正值仅为`127`,实际结果会变为负数`-128`(二进制`10000000`)。这种情况下,OF将被设置为1,表明存在溢出现象[^2]。 #### 3. **两者的主要区别** | 特性 | 进位标志 (CF) | 溢出标志 (OF) | |--------------------|--------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------| | 数据类型适用 | 只对**无符号数**有意义 | 专用于**有符号数** | | 判断依据 | 是否从最高有效位置向更高级别产生了进位或借位 | 结果是否超越了当前数据宽度所能表达的有效数值区间 | | 影响因素 | 数学上的简单进退位 | 考虑到符号位的变化及其合理性 | 综上所述,虽然CFOF都是用来监控特定条件下发生的异常状况,但它们关注的重点完全不同——前者侧重硬件层面的基础算术行为监测,后者更多涉及软件层面对合法数值界限的理解与控制。 ```python # 示例代码展示如何通过Python模拟简单的CFOF逻辑 def calculate_flags(a, b, bits=8): max_val = (1 << bits) - 1 signed_max = (1 << (bits - 1)) - 1 result = a + b cf = int(result > max_val or result < 0) # Convert to signed value for overflow check if a & (1 << (bits - 1)): a -= (1 << bits) if b & (1 << (bits - 1)): b -= (1 << bits) res_signed = a + b of = ((a ^ ~b) & (a ^ res_signed)) >> (bits - 1) return {"result": result % (max_val + 1), "cf": cf, "of": of} print(calculate_flags(127, 1, 8)) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值