0

在VS2013中调试x86汇编代码时,需要检查FLAGS寄存器的内容。但是,当我在注册窗口中启用“标志”时,我得到了:

OV = 0 上 = 0 EI = 1 PL = 1 ZR = 0 AC = 1 PE = 0 CY = 1

就我而言,我想检查 PL 符号值的状态。

那么多久更新一次?每一个动作?每个 ALU 操作?

编辑:我的 x86 教科书 kip irvine 汇编语言说

“Sign 标志是目标操作数高位的副本,表示设置为负,清除为正。(假设为零为正。)”

那么有一个目标操作数的指令?我不确定,因为这看起来很模糊。

4

1 回答 1

2

对于每条指令,都记录了它是否(以及如何)编写 EFLAGS。Intel 的指令集参考手册在每条指令的条目中都有一个 Flags Affected 部分。对于某些人来说,它只是无。

http://ref.x86asm.net/coder32.html有一个方便的指令表,包括一列显示它们读取和修改的标志,以及哪些修改的标志是明确定义的还是未定义的。(单击列标题以获取说明)。

大多数整数 ALU 指令,如suband add,会“根据结果”更新 FLAGS;这是设置 SF = 高位等常见描述的地方。cmp类似的 指令test 产生一个 FLAGS 结果,不修改任何一个整数输入。

lea并且not是不设置标志的值得注意的 ALU 异常。数据移动指令不设置 FLAGS,例如movpush/ pop。例如受影响的标志:无。

inc/dec设置除 CF 之外的标志,它们保持不变。(大多数 CPU 仍然可以有效地处理这个问题

SSE 和 fp 指令addsd xmm, xmm/mem通常不会写入标志。comisd xmm, xmm/mem您可以使用(SSE2) 或fcomi st?(x87 + Pentium Pro)在现代 x86 上将 FP 与 EFLAGS 进行比较。

英特尔第 2 卷手册中的一些示例:

以“有趣”方式编写标志的指令通常也在其“操作”部分伪代码中定义这一点。例如bsf

add:受影响的标志

OF、SF、ZF、AF、CF 和 PF 标志根据结果设置。

(如果您查看 Intel 的 vol.2 手册或 vol.1 的 PDF,我认为他们准确地定义了“根据结果”的含义。)

imul:受影响的标志:

对于单操作数形式的指令,当有效位进入结果的上半部分时设置 CF 和 OF 标志,并在结果正好适合结果的下半部分时清除标志。对于指令的二操作数和三操作数形式,当结果必须被截断以适合目标操作数大小时设置 CF 和 OF 标志,并在结果完全适合目标操作数大小时清除。SF、ZF、AF 和 PF 标志未定义。

sar//shlshr受影响的标志

CF 标志包含移出目标操作数的最后一位的值;对于计数大于或等于目标操作数的大小(以位为单位)的 SHL 和 SHR 指令,它是未定义的。OF 标志仅对 1 位移位产生影响(参见上面的“说明”);否则,它是未定义的。根据结果​​设置 SF、ZF 和 PF 标志。如果计数为 0,则标志不受影响。对于非零计数,AF 标志未定义。

为 count=0 保留未修改的标志是高性能实现要处理的另一个疯狂的 CISC 坑。(微架构必须为正确实现 x86 语义而支付的“x86 税”的一部分)。在英特尔 Sandybridge 系列上,这意味着可变计数移位(使用 count in cl)解码为 3 uop。SHLX(BMI2 无标志移位)只有 1 uop。


另一种回答“频率”问题的方法:每个时钟周期最多 4 次。或 5 在 Zen 或 Ice Lake。(每条指令最多一次。)

现代英特尔 CPU 是 4 宽超标量。它们可以在同一时钟周期内重命名 EFLAGS 4 次,允许它们在add reg,reg每个时钟周期运行 4 条独立指令,每条指令将其标志结果写入逻辑 EFLAGS 寄存器,但实际上是不同的物理寄存器。(并且真的在保存整数结果的物理寄存器上搭载 EFLAGS 输出,除非这样cmp的指令没有整数结果。)

https://agner.org/optimize/

于 2019-11-08T07:43:57.033 回答