简体   繁体   English

_InterlockedCompareExchange文档中“符号被忽略”的含义

[英]Meaning of “The sign is ignored” in _InterlockedCompareExchange documentation

The documentation for _InterlockedCompareExchange says for every parameter _InterlockedCompareExchange的文档说明了每个参数

The sign is ignored. 该标志被忽略。

So does it mean that numbers like 0xffff and 0x7fff (for 16-bit version) will be considered equal by _InterlockedCompareExchange16 etc. by other width intrinsics? 那么它是否意味着像其他宽度内在函数的_InterlockedCompareExchange16等对像0xffff0x7fff (对于16位版本)这样的数字会被认为是相等的? Or does this mean that the intrinsics accept both signed and unsigned integers? 或者这是否意味着内在函数接受有符号和无符号整数? Or something else? 或者是其他东西?

If it's not a bug in the documentation, it seems at least ambiguous. 如果它不是文档中的错误,那么它似乎至少是模棱两可的。

The sign bit is not ignored, it is compared just like the other bits. 符号位不被忽略,它与其他位进行比较。

The ..CompareExchange.. functions only care about the equality of the bits and does not interpret them in any special way. ..CompareExchange..函数只关心位的相等性,并不以任何特殊方式解释它们。 On x86 based systems they are implemented with the CMPXCHG / CMPXCHG8B instruction and it compares a CPU register against a memory location. 在基于x86的系统上,它们使用CMPXCHG / CMPXCHG8B指令实现,并将CPU寄存器与存储器位置进行比较。 The sign issue becomes a question about types and parameter passing, not the comparison itself. 符号问题成为关于类型和参数传递的问题,而不是比较本身。

Because most of the interlocked functions also exist as Windows API functions we can take a look at those first. 因为大多数互锁函数也作为Windows API函数存在,所以我们可以先看看它们。 The basic version takes 32-bit parameters with a LONG type. 基本版本采用LONG类型的32位参数。 Smaller signed types will be sign extended to 32-bits: 较小的签名类型将符号扩展为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

and this prints: 这打印:

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

32-bit x86: 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-bit x86_64/AMD64: 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

We can see that the generated code uses MOVSX to sign extend the 16-bit number. 我们可以看到生成的代码使用MOVSX来签名扩展16位数。 This is required by the Windows ABI. 这是Windows ABI所要求的。

When you use #pragma intrinsic(_InterlockedCompareExchange) things are a little less clear. 当你使用#pragma intrinsic(_InterlockedCompareExchange)事情就不那么清楚了。 I could not find a definitive statement in the documentation regarding the ABI of intrinsic functions but we can assume it follows the Windows ABI when it comes to sign extension. 我在文档中找不到关于内在函数的ABI的明确声明,但我们可以假设它在符号扩展时遵循Windows ABI。 The compiler will generate a LOCK CMPXCHG instruction directly without a function call but it will use MOVSX when required. 编译器将在没有函数调用的情况下直接生成LOCK CMPXCHG指令,但在需要时将使用MOVSX

the _InterlockedCompareExchange this is compiler intrinsic implemented as CMPXCHG instruction. _InterlockedCompareExchange这是编译器内部实现为CMPXCHG指令。 the The sign is ignored mean that when we compare 2 integers for equal only - no different how we interpret high bit - as sign bit or no. The sign is ignored意味着当我们比较2个整数只相等 - 没有不同我们如何解释高位 - 作为符号位或否。 this affected only compare for > or < but not for = . 这只影响了比较><但不是= and 0xffff of course not equal to 0x7fff 0xffff当然不等于0x7fff

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM