_InterlockedCompareExchange文档中"The sign is ignored"的含义

Meaning of "The sign is ignored" in _InterlockedCompareExchange documentation

本文关键字:ignored is The InterlockedCompareExchange 文档 sign      更新时间:2023-10-16

_InterlockedCompareExchange的文档说每个参数

标志被忽略。

那么,这是否意味着0xffff0x7fff(对于16位版本)等数字将被_InterlockedCompareExchange16等视为其他宽度内在的数字吗?还是这意味着内在的签名和未签名的整数?还是其他?

如果它不是文档中的错误,则似乎至少模棱两可。

符号位不被忽略,就像其他位一样比较。

..CompareExchange..的功能仅关心位的平等性,并且不会以任何特殊的方式解释它们。在基于X86的系统上,它们通过CMPXCHG/CMPXCHG8B指令实现,并将CPU寄存器与内存位置进行比较。符号问题成为有关类型和参数传递的问题,而不是比较本身。

由于大多数互锁功能也存在作为Windows API函数,因此我们可以首先查看这些功能。基本版本使用LONG类型采用32位参数。较小的签名类型将被签名到32位:

__declspec(noinline) void WINAPI Number(LONG val)
{
    printf("Number: %5d %#.8x (%d bit)n", val, val, sizeof(void*) * 8); 
}
__declspec(noinline) INT16 WINAPI GetI16(INT16 num)
{
    return num;
}
...
Number(0xffff); // Not sign extended
const INT16 numi16 = -42;
Number(numi16); // Optimized to 32-bit parameter by the compiler
Number(GetI16(-42)); // Use a helper function to prevent compiler tricks

此打印:

Number: 65535 0x0000ffff (64 bit)
Number:   -42 0xffffffd6 (64 bit)
Number:   -42 0xffffffd6 (64 bit)

32位x86:

; 1040 :    Number(0xffff);
  00022 68 ff ff 00 00  push     65535          ; 0000ffffH
  00027 e8 00 00 00 00  call     ?Number@@YGXJ@Z        ; Number
; 1041 :    const INT16 numi16 = -42;
; 1042 :    Number(numi16);
 0002c  6a d6           push     -42            ; ffffffd6H
 0002e  e8 00 00 00 00  call     ?Number@@YGXJ@Z        ; Number
; 1047 :    Number(GetI16(-42));
 00033  6a d6           push     -42            ; ffffffd6H
 00035  e8 00 00 00 00  call     ?GetI16@@YGFF@Z        ; GetI16
 0003a  0f bf c0        movsx  eax, ax
 0003d  50              push     eax
 0003e  e8 00 00 00 00  call     ?Number@@YGXJ@Z        ; Number

64位x86_64/amd64:

; 1040 :    Number(0xffff);
  00027 b9 ff ff 00 00  mov  ecx, 65535     ; 0000ffffH
  0002c e8 00 00 00 00  call     ?Number@@YAXJ@Z        ; Number
; 1041 :    const INT16 numi16 = -42;
; 1042 :    Number(numi16);
  00031 b9 d6 ff ff ff  mov  ecx, -42       ; ffffffffffffffd6H
  00036 e8 00 00 00 00  call     ?Number@@YAXJ@Z        ; Number
; 1047 :    Number(GetI16(-42));
  0003b 66 b9 d6 ff     mov  cx, -42        ; ffffffffffffffd6H
  0003f e8 00 00 00 00  call     ?GetI16@@YAFF@Z        ; GetI16
  00044 0f bf c8        movsx    ecx, ax
  00047 e8 00 00 00 00  call     ?Number@@YAXJ@Z        ; Number

我们可以看到生成的代码使用MOVSX签名扩展16位号。这是Windows Abi的要求。

当您使用#pragma intrinsic(_InterlockedCompareExchange)时,事情还不太清楚。我在文档中找不到有关内在函数ABI的确定性语句,但是我们可以假设它在签名扩展时遵循Windows ABI。编译器将直接生成LOCK CMPXCHG指令,而无需函数调用,但需要在需要时使用MOVSX

_InterlockedCompareExchange这是以CMPXCHG指令实现的编译器的固有性。The sign is ignored意味着,当我们将2个整数与相等的仅比较时 - 我们如何解释高位 - 为符号或否。这仅与><进行比较,但不适合=0xffff当然不等于0x7fff