【问题标题】:Carry Flag Compare, when is the carry flag set?进位标志比较,什么时候设置进位标志?
【发布时间】:2018-09-11 00:38:27
【问题描述】:

汇编器有这样的代码:

sub$0x22,%eax # %eax = %eax - 22
cmp$0x7,%eax  # %eax > 7 then jump *this is where I have trouble*
ja some address # jump if C = 1 or Z = 1

我的目标是不跳。 我尝试过 %eax = 30, 14, 28, 16, 0 , 22 的情况

问题: 在我尝试过的所有案例中,我不明白为什么 c=0 和 z=0 。

【问题讨论】:

  • 这些样本 eax 值是十六进制还是十进制?
  • ja 将在 CF 和 ZF 为 0 时跳转,而不是“如果 C = 1 或 Z = 1”。第一行确实减去 0x22(十六进制)= 34 十进制,所以你的测试值是什么格式的? 28 还是 0x28?使用 0x28(十进制 40)-> eax = 6 (0x28 - 0x22),cmp $7,%eax 将设置 CF=1,ZF=0,跳转将被忽略。
  • 可能会添加输入值范围的描述,当您期望跳转时,何时不跳转,以便可以向您显示正确的代码,您当前的代码不会跳转到 eax 值的“某个地址”从范围 0x22 (34) .. 0x29 (41)。其他一切都会跳跃。该代码看起来像常见的惯用方式,如何将 eax 限制在某个值范围内并将其标准化为最小值,即经常用于检查值是否为 ASCII 数字(将检查范围 0x30..0x39 并因此使用 sub $0x30,%eax @ 987654325@ ja not_ascii_digit 和这里 eax 包含值 0..9 取决于输入字符)
  • 感谢您的澄清!

标签: assembly x86 att


【解决方案1】:

0x22 是十进制的 34,大于所有这些样本 eax 值(假设它们是十进制的)。因此,减法的结果是否定的。但“负”整数只是最高有效位为 1 的整数,也可以解释为大的无符号数。

考虑ja 在概念上的含义而不是标志上的实际逻辑可能更容易。 (see this answer) 您可以将ja 视为无符号比较。因此,这些负数看起来像大于 7 的非常大的数字。如果您改用 jg 指令,它的行为应该更像您所期望的。它可以被认为是一个有符号的比较。

【讨论】:

  • 注意:JA 是基于 CF,而不是 SF。所以重要的是结转,而不是sub 结果的最高位。对于小的正输入,这些恰好是同一件事,但通常情况并非如此。
猜你喜欢
  • 1970-01-01
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-03
  • 2011-03-09
  • 2019-09-08
相关资源
最近更新 更多