x86 程序集 - CMP 未正确设置零标志
x86 assembly - CMP not setting zero flag correctly
我在调试时遇到了这个比较:
| 38 19 | CMP BYTE PTR DS:[ECX], BL
我在上面设置了一个断点并看到了这个(hex 中的值):
ECX = 00838430
BYTE PTR[ECX]=[00838430]=55
EBX = 00000055 (BL = 55)
EFLAGS = 00000314 (CF=0 OF=0 SF=0 ZF=0 AF=1 PF=1)
所以我希望在执行此比较后设置零标志,因为 ECX 和 BL 指向的字节相等。然而,相反发生的是设置了溢出标志并且 ZF 保持为 0。比较之后:
EFLAGS = 00000A06 (CF=0 OF=1 SF=0 ZF=0 AF=0 PF=1)
为什么会这样?它与 signed/unsigned 整数有关吗?我认为 CMP 是不可知的,即将比较的结果解释为 signed/unsigned 是以下分支指令会做的事情(例如 JG vs JA)。比较后跟一个 JNE,因为 ZF=0 而导致不正确的结果。
我怀疑调试器有什么问题,所以我尝试了另一个(OllyDbg v2),发现我发布的值确实是正确的,有 55在内存和 BL 中。然而,运行在 Olly 的领导下,CMP 的行为与预期的一样正确,即设置了 ZF 并且没有进行跳跃。
所以代码实际上按预期工作,问题出在调试器上。当代码不在调试器下 运行ning 时,它也能正常工作。对于这个特定的代码,在没有调试器的情况下测试正确性有点困难和耗时,这就是为什么我到目前为止从未在没有调试器的情况下测试过它。该错误与断点或 single-stepping 无关,因为它在 运行 时也无法正常工作。
有 bug 的调试器是 x64dbg(尽管名称如此,但它不仅适用于 64 位)。我的构建已经有点过时了,也许这个错误在最新的快照中得到了修复。
感谢大家的评论。
这实际上是用户错误,而不是调试器中的错误。在 00838430 处设置了一个 INT3 断点,我忘记了,或者我可能暂时忘记了软件断点是如何工作的。不管怎样,在这种情况下内存的实际内容是 0xCC,但调试器显示的是原始字节。因此,CMP 的行为完全符合其应有的行为。 Ped7g 从第一条评论说我应该 double-check 内存内容是正确的。使用另一个调试器的第二次测试工作正常,只是因为我当时没有在 00838430 设置断点。
我在调试时遇到了这个比较:
| 38 19 | CMP BYTE PTR DS:[ECX], BL
我在上面设置了一个断点并看到了这个(hex 中的值):
ECX = 00838430
BYTE PTR[ECX]=[00838430]=55
EBX = 00000055 (BL = 55)
EFLAGS = 00000314 (CF=0 OF=0 SF=0 ZF=0 AF=1 PF=1)
所以我希望在执行此比较后设置零标志,因为 ECX 和 BL 指向的字节相等。然而,相反发生的是设置了溢出标志并且 ZF 保持为 0。比较之后:
EFLAGS = 00000A06 (CF=0 OF=1 SF=0 ZF=0 AF=0 PF=1)
为什么会这样?它与 signed/unsigned 整数有关吗?我认为 CMP 是不可知的,即将比较的结果解释为 signed/unsigned 是以下分支指令会做的事情(例如 JG vs JA)。比较后跟一个 JNE,因为 ZF=0 而导致不正确的结果。
我怀疑调试器有什么问题,所以我尝试了另一个(OllyDbg v2),发现我发布的值确实是正确的,有 55在内存和 BL 中。然而,运行在 Olly 的领导下,CMP 的行为与预期的一样正确,即设置了 ZF 并且没有进行跳跃。
所以代码实际上按预期工作,问题出在调试器上。当代码不在调试器下 运行ning 时,它也能正常工作。对于这个特定的代码,在没有调试器的情况下测试正确性有点困难和耗时,这就是为什么我到目前为止从未在没有调试器的情况下测试过它。该错误与断点或 single-stepping 无关,因为它在 运行 时也无法正常工作。
有 bug 的调试器是 x64dbg(尽管名称如此,但它不仅适用于 64 位)。我的构建已经有点过时了,也许这个错误在最新的快照中得到了修复。
感谢大家的评论。
这实际上是用户错误,而不是调试器中的错误。在 00838430 处设置了一个 INT3 断点,我忘记了,或者我可能暂时忘记了软件断点是如何工作的。不管怎样,在这种情况下内存的实际内容是 0xCC,但调试器显示的是原始字节。因此,CMP 的行为完全符合其应有的行为。 Ped7g 从第一条评论说我应该 double-check 内存内容是正确的。使用另一个调试器的第二次测试工作正常,只是因为我当时没有在 00838430 设置断点。