Assembly x86-32汇编中128位无符号整数的比较

Assembly x86-32汇编中128位无符号整数的比较,assembly,x86,comparison,Assembly,X86,Comparison,我试图在2个128位整数之间进行比较,但我似乎搞不懂 具体来说,我有一大堆IPv6 IP地址(分配块的起始地址和结束地址),我试图确定这些块之间是否有特定的IP地址,所以这不是直接比较,更像是试图检查是否大于起始地址和小于结束地址 如果这有什么不同的话,我正在将WinAsm Studio与MASM32一起使用 对IPv4地址执行此操作很简单,但是,我不知道如何对128位无符号整数(4 x DWORD)执行此操作 先谢谢你 否则,只需使用从最重要的块开始的标量代码进行范围检查 在使用cmp和标志寄

我试图在2个128位整数之间进行比较,但我似乎搞不懂

具体来说,我有一大堆IPv6 IP地址(分配块的起始地址和结束地址),我试图确定这些块之间是否有特定的IP地址,所以这不是直接比较,更像是试图检查是否大于起始地址和小于结束地址

如果这有什么不同的话,我正在将WinAsm Studio与MASM32一起使用

对IPv4地址执行此操作很简单,但是,我不知道如何对128位无符号整数(4 x DWORD)执行此操作

先谢谢你

否则,只需使用从最重要的块开始的标量代码进行范围检查

在使用
cmp
和标志寄存器的CPU上,这是通过以下方式完成的:

  • 比较数字的最高部分(例如最高32位)(
    cmp
    指令)
  • 如果不是“相等”,则跳转到“EndOfCompare”(x86:
    jne
    指令)
  • 比较数字的下一部分(例如32位)
  • 如果不是“相等”,则跳转到“EndOfCompare”
  • 比较数字的下一部分(例如32位)
  • 如果不是“相等”,则跳转到“EndOfCompare”
  • 比较数字的最低部分(例如最低32位)
  • “EndOfCompare”:
    此时,标志寄存器包含关于两个大数字的顺序(
    ab
    )的信息,就像比较两个小数字的简单
    cmp
    指令一样
不幸的是,这个简单的变体只适用于无符号数字

顺便说一句,通常一个块在IP地址空间中是“对齐”的,所以你只需要检查屏蔽掉低位并比较高位是否相等

检查
(A和掩码)=(B和掩码)
可以通过以下方式在32位CPU上完成:

mov ecx, part 1 of A
xor ecx, part 1 of B
and ecx, part 1 of MASK

mov eax, part 2 of A
xor eax, part 2 of B
and eax, part 2 of MASK
or  ecx, eax

mov eax, part 3 of A
xor eax, part 3 of B
and eax, part 3 of MASK
or  ecx, eax
...
对于128位数字,需要4个“部件”

“第1部分”是数字的高位还是低位并不重要


如果
(A和MASK)=(B和MASK)
为真,
ecx
的值为0(并且由于
指令将设置零标志)。

您是否可以假设SSE2并使用
pcmpgtd
(范围转换为有符号后)使其更有效?否则,只需使用从最重要的块开始的标量代码进行范围检查。查看32位编译器输出以比较64位无符号整数,并将其扩展到另外两个块。顺便说一句,通常一个块在IP地址空间中是“对齐”的,因此您只需检查掩码,去掉低位并比较高位是否相等。谢谢Peter,让我来玩一玩,第二个选项比第一个更容易接受SSE2使屏蔽比较非常有效(如果您可以从
/64
或任何实际为移位计数的网络掩码有效地生成屏蔽)。只需屏蔽这两个代码,然后
pcmpeqd
/
pmovmskb
。非常感谢Peter和Martin,我喜欢上面示例代码的外观,我将在周二回家后玩一玩。我的x86技能不足,至少可以说,目前使用SSE2对我来说是非常困难的。@colinr:那你为什么要用asm而不是C来编写编译器可能会自动矢量化的代码呢?通常,只有在比编译器更了解如何优化目标微体系结构的情况下,使用asm编写才有意义。@peter,我曾经在MC68000上大量使用asm编写代码,在编写代码时中断了很长时间,然后开始使用x86,这是我当时的逻辑步骤。我学到了一些C++,但我发现它很难铸造。在ASM中,字节只是一个字节,不管有符号、无符号或ASCII值。@ Cyrr:是的,C++和符号溢出UB使它不是真正的可移植汇编语言。但是
uint8\u t
可以像
'a'
那样存储字符文本的值。只有当像
std::cout这样的事情发生时,它才会变得烦人