簡體   English   中英

_InterlockedCompareExchange文檔中“符號被忽略”的含義

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

_InterlockedCompareExchange的文檔說明了每個參數

該標志被忽略。

那么它是否意味着像其他寬度內在函數的_InterlockedCompareExchange16等對像0xffff0x7fff (對於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM