不理解 FLAGS 状态寄存器
Not understanding FLAGS status register
我正在帮助我的一个朋友做一些计算机体系结构理论练习。我们偶然发现了这个 m.c。关于 FLAGS 寄存器的练习,真的不知道如何回答。事情是这样的:
"Assume that you've performed an ADD operation between two unsigned integer numbers, and that it resulted in the following flags setting: CF = 0; OF = 1; ZF=0; SF=1 . What can we conclude from this setting and why?"
正确的选择表明该操作的结果是正确的,而在说明原因时,它表明“因为 CF 等于零”。我的问题是为什么当其他标志设置为一个时我们只需要考虑进位标志?而且,当我们在无符号整数之间执行加法运算时,如何将溢出和有符号标志设置为 1?
提前致谢!
进位标志反映了从操作的最高有效位生成进位。对于无符号操作数,这样的进位将反映溢出。
至于其他标志,Sign标志仅适用于有符号操作数。溢出标志也是如此,因为它是在符号因签名操作溢出而错误更改时设置的。
最终标志零在结果为零时设置,与溢出检测无关。
在您提供的示例中,操作数是无符号的并且进位标志被清除。所以没有发生溢出。
CF=0 告诉你 ADD 没有换行。参见 this article on Understanding Carry vs. Overflow conditions/flags 。
你可以说 ADD 总是给出正确的 (a + b) modulo 2^32
结果,除非你的电脑坏了。如果 ADD 环绕,结果与两个输入的无限精度数学和不同,但它是正确的模运算(免费进行模运算)。所以你必须小心你所说的 "correct" 是什么意思! (很明显,在这种情况下,您的分配意味着数学整数和。)
这里的术语令人困惑,因为 "arithmetic overflow" 作为一个一般概念(当数学上精确的结果不能适合目标时)包括有符号和无符号整数的情况。在 x86 上(与所有普通 CPU 一样),行为是环绕式的。但是无符号环绕称为进位,而有符号环绕称为溢出。
对于浮点数,正常的溢出行为是饱和到 +/- 无穷大。这说明了作为一般概念的溢出与作为整数溢出的特定行为的环绕之间的区别。
一些架构有一个饱和加指令,饱和作为整数溢出行为。 x86 具有用于整数 SIMD 的 paddusw
指令(和签名版本),但不用于像 EAX 这样的标量 GP 寄存器。
在 C 中,无符号溢出被定义为环绕,但有符号溢出是未定义的行为(并且编译器可以在假设它不会发生的情况下进行优化)。
MIPS 有一条 add
指令会在有符号溢出时陷入陷阱。 (不过,C 编译器通常对所有内容都使用 addu
,因为 MIPS 是一个 2 的补码机,所以它的二进制操作相同,只是捕获行为不同。他们只能安全地使用 add
来捕获有符号溢出 UB当他们添加的东西与 C 抽象机中出现的变量值相匹配时,而不是在优化之后。一些 bithack 代码不安全地依赖于 C 中的签名环绕,因此用户通常希望环绕而不是捕获。MIPS 没有任何类型的 FLAGS 寄存器,因此他们决定为溢出检查加法提供硬件支持。)
其余标志为您提供有关结果的更多信息
其中一些很少/从来没有用,但这是我对 "what can you conclude?" 的回答。
ZF=0 告诉你结果是非零的。如果你正在实现类似 if (a + b != 0)
的东西,你可以在 ADD 设置的标志上分支(或 cmov 或 setcc),而不是单独执行 test eax,eax
。在 cmp 或 test 以外的指令后使用 ZF 的情况并不少见。
SF=1 告诉你结果 >= 最大值的一半。即无符号结果设置了高位。对于 8 位 ADD,SF=1 表示结果 >= 128。
这有时可以为您节省测试或比较说明。如果您将一个寄存器添加到自身作为左移,那么 CF 会将位移出,而 SF 会具有当前的高位。我想 OF 告诉你一些关于
的事情
OF=1(SF=1 且 CF=0)告诉您两个输入都小于最大无符号值的一半。 (即,如果解释为有符号数,则它们为正。结果的有符号解释为负,因此结果的有符号解释为 pos + pos = neg,这只能通过溢出发生)。
我从来没有在我写的任何 asm 中利用最后一个,它似乎不太可能有用。我所知道的任何架构都没有同时查看 CF 和 OF 的分支条件。所以它只有在你已经在 CF=0 分支中才有用。 x86 已经签署了更大/更少的分支 that check SF != OF,但是你仍然不能用一条指令检查 SF==1 和 OF==1。所以如果你想检查那个条件,你可能会 OR
两个输入并检查它的 SF。
我正在帮助我的一个朋友做一些计算机体系结构理论练习。我们偶然发现了这个 m.c。关于 FLAGS 寄存器的练习,真的不知道如何回答。事情是这样的:
"Assume that you've performed an ADD operation between two unsigned integer numbers, and that it resulted in the following flags setting: CF = 0; OF = 1; ZF=0; SF=1 . What can we conclude from this setting and why?"
正确的选择表明该操作的结果是正确的,而在说明原因时,它表明“因为 CF 等于零”。我的问题是为什么当其他标志设置为一个时我们只需要考虑进位标志?而且,当我们在无符号整数之间执行加法运算时,如何将溢出和有符号标志设置为 1?
提前致谢!
进位标志反映了从操作的最高有效位生成进位。对于无符号操作数,这样的进位将反映溢出。
至于其他标志,Sign标志仅适用于有符号操作数。溢出标志也是如此,因为它是在符号因签名操作溢出而错误更改时设置的。
最终标志零在结果为零时设置,与溢出检测无关。
在您提供的示例中,操作数是无符号的并且进位标志被清除。所以没有发生溢出。
CF=0 告诉你 ADD 没有换行。参见 this article on Understanding Carry vs. Overflow conditions/flags 。
你可以说 ADD 总是给出正确的 (a + b) modulo 2^32
结果,除非你的电脑坏了。如果 ADD 环绕,结果与两个输入的无限精度数学和不同,但它是正确的模运算(免费进行模运算)。所以你必须小心你所说的 "correct" 是什么意思! (很明显,在这种情况下,您的分配意味着数学整数和。)
这里的术语令人困惑,因为 "arithmetic overflow" 作为一个一般概念(当数学上精确的结果不能适合目标时)包括有符号和无符号整数的情况。在 x86 上(与所有普通 CPU 一样),行为是环绕式的。但是无符号环绕称为进位,而有符号环绕称为溢出。
对于浮点数,正常的溢出行为是饱和到 +/- 无穷大。这说明了作为一般概念的溢出与作为整数溢出的特定行为的环绕之间的区别。
一些架构有一个饱和加指令,饱和作为整数溢出行为。 x86 具有用于整数 SIMD 的 paddusw
指令(和签名版本),但不用于像 EAX 这样的标量 GP 寄存器。
在 C 中,无符号溢出被定义为环绕,但有符号溢出是未定义的行为(并且编译器可以在假设它不会发生的情况下进行优化)。
MIPS 有一条 add
指令会在有符号溢出时陷入陷阱。 (不过,C 编译器通常对所有内容都使用 addu
,因为 MIPS 是一个 2 的补码机,所以它的二进制操作相同,只是捕获行为不同。他们只能安全地使用 add
来捕获有符号溢出 UB当他们添加的东西与 C 抽象机中出现的变量值相匹配时,而不是在优化之后。一些 bithack 代码不安全地依赖于 C 中的签名环绕,因此用户通常希望环绕而不是捕获。MIPS 没有任何类型的 FLAGS 寄存器,因此他们决定为溢出检查加法提供硬件支持。)
其余标志为您提供有关结果的更多信息
其中一些很少/从来没有用,但这是我对 "what can you conclude?" 的回答。
ZF=0 告诉你结果是非零的。如果你正在实现类似 if (a + b != 0)
的东西,你可以在 ADD 设置的标志上分支(或 cmov 或 setcc),而不是单独执行 test eax,eax
。在 cmp 或 test 以外的指令后使用 ZF 的情况并不少见。
SF=1 告诉你结果 >= 最大值的一半。即无符号结果设置了高位。对于 8 位 ADD,SF=1 表示结果 >= 128。 这有时可以为您节省测试或比较说明。如果您将一个寄存器添加到自身作为左移,那么 CF 会将位移出,而 SF 会具有当前的高位。我想 OF 告诉你一些关于
的事情OF=1(SF=1 且 CF=0)告诉您两个输入都小于最大无符号值的一半。 (即,如果解释为有符号数,则它们为正。结果的有符号解释为负,因此结果的有符号解释为 pos + pos = neg,这只能通过溢出发生)。
我从来没有在我写的任何 asm 中利用最后一个,它似乎不太可能有用。我所知道的任何架构都没有同时查看 CF 和 OF 的分支条件。所以它只有在你已经在 CF=0 分支中才有用。 x86 已经签署了更大/更少的分支 that check SF != OF,但是你仍然不能用一条指令检查 SF==1 和 OF==1。所以如果你想检查那个条件,你可能会 OR
两个输入并检查它的 SF。