CF 标志的行为难以理解

2024-03-10

假设有一段代码:

mov al, 12
mov bl, 4
sub al, bl

在这种情况下,CF = 0 标志,但在我看来它应该等于 1,因为减法运算是在加法运算上实现的,并且处理器不知道我们将其作为输入提供什么,无论是有符号还是无符号数字,它只是完成它的工作。

也就是说,上面的代码相当于下面的代码:

在al寄存器中输入值12,即0000 1100

在bl寄存器中输入值4,即0000 0100

接下来是减法运算,因为第一个操作数是正数,所以没有转换为附加代码。由于第二个也是正数,所以也没有变换,但是由于执行了减法运算,所以第二个操作数被翻译成额外的代码,处理器执行加法运算(减法是通过加法实现的),即:

12: 0000 1100
-4: 1111 1100



12 - 4 = 12 + (-4) = 0000 1100 + 1111 1100 = 1 0000 1000

也就是说,我们得到了正确的结果 - 8,但如果调试它,CF = 0。这是为什么?超出位格的放在CF中,但CF=0。


阅读手册后,CF标志表示无符号溢出。然而,这并不意味着额外的溢出。

您假设设置的位 8 指示溢出,但是,减法的情况相反。如果未设置,则表明借位发生在位向上。

如果我们更换4 with 16,这样我们就会看到溢出:

00001100b - 00010000b = 00001100b + 11110000b = 11111100b = 252d

您可以看到,尽管发生了无符号溢出,但直到第 8 位都没有进位。 CF 标志不是进位加负数的结果。它只是表明减法溢出。在这种情况下,这意味着它与溢出位相反。


不同的体系结构对进位标志的处理方式不同。有些人用它来表示发生了借位,而另一些人则用它来表示要借用的位。他们经常有一个指令(sbb在 x86 中),允许通过使用标志作为输入的一部分进行链接。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CF 标志的行为难以理解 的相关文章

  • 寄存器寻址模式与直接寻址模式

    我在试卷中遇到过这个问题 它指出 哪种给定的寻址模式更快 为什么 寄存器寻址方式 直接寻址方式 现在根据我的说法 寄存器寻址模式应该更快 因为寄存器是计算机中最快的存储位置 这是正确答案吗 请帮忙 谢谢 两种寻址模式之间的区别是 地址的来源
  • 有没有办法使用 i387 fsqrt 指令获得正确的舍入?

    有没有办法使用 i387 fsqrt 指令获得正确的舍入 除了改变精确模式在 x87 控制字中 我知道这是可能的 但这不是一个合理的解决方案 因为它存在令人讨厌的重入型问题 如果 sqrt 操作中断 精度模式将出错 我正在处理的问题如下 x
  • 如何知道寄存器是否是“通用寄存器”?

    我试图了解寄存器必须具备什么标准才能被称为 通用寄存器 我相信通用寄存器是一个可以用于任何用途的寄存器 用于计算 将数据移入 移出等 并且是一个没有特殊用途的寄存器 现在我读到了ESP寄存器是通用寄存器 我猜是ESP寄存器可以用于任何事情
  • 从 NASM 调用 C 函数 _printf 会导致分段错误

    我一直在尝试使用 NASM 在 Mac OS 和 Windows 上学习 64 位汇编 我的代码是 extern printf section data msg db Hello World 10 0 section text global
  • 弹出 x86 堆栈以访问函数 arg 时出现分段错误

    我正在尝试链接 x86 程序集和 C 我的C程序 extern int plus 10 int include
  • 使用 (float&)int 进行类型双关可以正常工作,(float const&)int 会像 (float)int 一样转换吗?

    VS2019 发布 x86 template
  • ARMv8 A64 汇编中立即值的范围

    我的理解是 ARMv8 A64 汇编中的立即参数可以是 12 位长 如果是这样的话 为什么这行汇编代码是 AND X12 X10 0xFEF 产生此错误 使用 gcc 编译时 Error immediate out of range at
  • 阴影空间示例

    EDIT 我接受了下面的答案 并添加了我自己的代码的最终修订版 希望它向人们展示影子空间分配的实际示例 而不是更多的文字 编辑 2 我还设法在 YouTube 视频 所有内容 的注释中找到了一个调用约定 PDF 的链接 其中有一些关于 Li
  • 如何仅使用单个数组在 JavaScript 中模拟调用堆栈

    我正在看维基百科页面 https en wikipedia org wiki Call stack在调用堆栈上 并尝试理解这个图像 据我所知 哈哈 const memory memory 0 3 top of stack pointer m
  • GCC的sqrt()编译后如何工作?使用哪种root方法?牛顿-拉夫森?

    只是对标准感到好奇sqrt 来自 GCC 上的 math h 我自己编码的sqrt 使用牛顿拉夫森来做到这一点 是的 我知道 fsqrt 但CPU是如何做到这一点的呢 我无法调试硬件 现代 CPU 中的典型 div sqrt 硬件使用 2
  • 在 x86 程序集中存储大量布尔值的最佳方法是什么?

    最近我一直在处理充满布尔值的大型数组 目前 我将它们存储在 bss部分有一个 space指令 它允许我创建字节数组 但是 由于我只需要存储布尔值 因此我希望从数组中逐位读取和写入数据 目前 我能想到的最好方法是有一个 space指令所需存储
  • 在 x86 汇编中将 64 位常量移至内存

    我正在使用 Intel x64 程序集 NASM 编译器 尝试将 0x4000000000000000 常量移至内存 该常量在 ieee 754 标准双精度中应等于 2 0 我正在使用的代码是 define two 0x4000000000
  • 错误 LNK2019:函数 main 中引用的外部符号无法解析

    我正在尝试在 C 中运行我的简单汇编代码 我只有两个文件 cpp 文件和 asm 文件 编译时出现错误 见下文 如果有人可以提供帮助 我将不胜感激 这是我的 main cpp 文件 include
  • 高效memcspn

    有谁知道 memcspn 函数的有效实现吗 它的行为应该类似于 strcspn 但在内存缓冲区中查找跨度 而不是在以 null 结尾的字符串中查找跨度 目标编译器是 VisualC 谢谢 卢卡 一种近乎最佳的实现 size t memcsp
  • 为什么 Linux perf 使用事件 l1d.replacement 来处理 x86 上的“L1 dcache misses”?

    在英特尔 x86 上 Linux用途 https stackoverflow com a 52172985 149138事件l1d replacements来实施其L1 dcache load misses event 该事件定义如下 计数
  • NASM 中的 equ 和 db 有什么区别?

    len equ 2 len db 2 它们是否相同 产生可以用来代替的标签2 如果不是 那么每种申报表的优点或缺点是什么 它们可以互换使用吗 第一个是equate 与 C 类似 define len 2 因为它实际上并没有在最终代码中分配任
  • 避免 gcc 函数序言开销?

    我最近遇到了很多 gcc 在 x86 上生成非常糟糕的代码的函数 它们都符合以下模式 if some condition do something really simple and return else something comple
  • 为什么X86中没有NAND、NOR和XNOR指令?

    它们是您可以在计算机上执行的最简单的 指令 之一 它们是我亲自实施的第一个指令 执行 NOT AND x y 会使执行时间和依赖链长度和代码大小加倍 BMI1 引入了 andnot 这是一个有意义的补充 是一个独特的操作 为什么不是这个问题
  • 何时可以重用avx指令中的源寄存器

    在 avx 指令中用作源的寄存器何时可以在指令开始处理后重用 例如 我想使用vgatherdps该指令消耗两个 ymm 寄存器 其中之一是位移索引 我意识到vgatherdps由于数据的局部性较差 因此需要花费大量时间来收集 位移索引寄存器
  • 汇编器8086将32位数字除以16位数字

    我尝试将 32 位数字除以 16 位数字 例如 10000000h 除以 2000h 根据我尝试做的设计除以 右 4 位数字除以除数 然后左 4 位数字除以除数 这是我的代码 DATA num dd 10000000h divisor dw

随机推荐