【问题标题】:How to compare a signed value and an unsigned value in x86 assembly如何在 x86 程序集中比较有符号值和无符号值
【发布时间】:2015-02-01 19:02:52
【问题描述】:

我无法找到一种方法来比较 x86 汇编代码中的正数和负数。

例如:当我比较 -1 和 1 时,我总是得到 -1 更大。我知道这是因为 2 的补码格式使基础二进制中的 -1 大于 1。

但是任何人都可以提供 x86 程序集的 sn-p 来比较正数和负数并使其在数学上正确吗? (例如 1 > -1)

谢谢!

【问题讨论】:

  • 一个不一定是未签名的。有符号和无符号比较是相同的 - 这完全取决于您如何解释标志。那么,您如何解释标志? :)

标签: assembly binary x86 x86-64


【解决方案1】:

可能使用了以下无符号变体之一:

cmp  eax, ebx
jb   lesser

有等价物可以相互检查带符号的数字,例如:

cmp  eax, ebx
jl   lesser

This link 对跳跃变化进行了很好的总结,包括它们的签名和他们检查的标志,部分复制在这里以进行自我控制:

Instruction  Jump if ...           Signed?   Flags
-----------  -----------           --------  -----
JO           overflow                        OF=1
JNO          not overflow                    OF=0
JS           sign                            SF=1
JNS          not sign                        SF=0
JE/JZ        equal
             zero                            ZF=1
JNE/JNZ      not-equal
             not-zero                        ZF=0
JB/JNAE/JC   below
             not-above-or-equal
             carry                 unsigned  CF=1
JNB/JAE/JNC  not-below
             above-or-equal
             no-carry              unsigned  CF=0
JBE/JNA      below-or-equal
             not-above             unsigned  CF=1 or ZF=1
JA/JNBE      above
             not-below-or-equal    unsigned  CF=0 and ZF=0
JL/JNGE      less
             not-greater-or-equal  signed    SF<>OF
JGE/JNL      greater-or-equal
             not-less              signed    SF=OF
JLE/JNG      less-or-equal
             not-greater           signed    ZF=1 or SF<>OF
JG/JNLE      greater
             not-less-or-equal     signed    ZF=0 and SF=OF
JP/JPE       parity
             parity-even                     PF=1
JNP/JPO      not-parity
             parity-odd                      PF=0
JCXZ/JECXZ   CX register is zero
             ECX register is zero

【讨论】:

    【解决方案2】:

    您不能直接比较具有不同符号的两个数字。实际上大多数软件语言都有这种流程。 C 和 C++ 在其文档中特别提到,当您在同一表达式中使用有符号和无符号整数时,在大多数情况下会生成警告,这可能会导致未知符号。

    唯一的方法是首先检查带符号的数字是否为负数,如果是,则知道它更小。然后您可以将这两个数字作为无符号整数进行比较。

    ; is eax < ebx (eax signed, ebx unsigned)
    
    cmp eax, $0
    jl less
    
    cmp eax, ebx
    jc less
    

    旁注:如果两个数字的大小小于处理器支持的最大大小,则显然可以比较两个带符号的数字。在这种情况下,您可以适当地扩展有符号和无符号的位,然后您可以像两个值都已签名一样进行比较。

    假设你想比较两个字节 al 和 bl,那么你可以有这样的东西:

    movsx ax, al
    xor bh, bh    ; or movzx bx, bl
    cmp ax, bx
    jl less
    

    (注意,我不保证jl是正确的,可能是jle或者jnl...)

    【讨论】:

    • 在 32 位模式下,movsx eax, al / movzx ebx, bl 将是最有效的方式。 (也在现代 x86 上的 16 位模式下,以避免错误的依赖关系)。无论如何,除非您需要代码在 pre-386 movzx bx, bl 上工作,否则比编写 BH 然后在大多数 CPU 上读取 BX 更好。
    猜你喜欢
    • 2012-09-30
    • 2015-10-31
    • 2019-07-11
    • 1970-01-01
    • 2012-07-28
    • 2014-01-28
    • 1970-01-01
    • 2011-07-21
    相关资源
    最近更新 更多