[英]Meaning of “The sign is ignored” in _InterlockedCompareExchange documentation
_InterlockedCompareExchange
的文档说明了每个参数
该标志被忽略。
那么它是否意味着像其他宽度内在函数的_InterlockedCompareExchange16
等对像0xffff
和0x7fff
(对于16位版本)这样的数字会被认为是相等的? 或者这是否意味着内在函数接受有符号和无符号整数? 或者是其他东西?
如果它不是文档中的错误,那么它似乎至少是模棱两可的。
符号位不被忽略,它与其他位进行比较。
..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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.