2016-12-27 71 views
0

我正在瀏覽以下代碼並遇到以下代碼段。奇怪的按位運算符組合的目的是什麼?

https://www.virtualbox.org/svn/vbox/trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Hob/Hob.c

EFI_STATUS 
EFIAPI 
PeiCreateHob ( 
    IN CONST EFI_PEI_SERVICES **PeiServices, 
    IN UINT16   Type, 
    IN UINT16   Length, 
    IN OUT VOID   **Hob 
) 
{ 
    EFI_STATUS       Status; 
    EFI_HOB_HANDOFF_INFO_TABLE   *HandOffHob; 
    EFI_HOB_GENERIC_HEADER    *HobEnd; 
    EFI_PHYSICAL_ADDRESS     FreeMemory; 


    Status = PeiGetHobList (PeiServices, Hob); 
    if (EFI_ERROR(Status)) { 
    return Status; 
    } 

    HandOffHob = *Hob; 

    // 
    // Check Length to avoid data overflow. 
    // 
    if (0x10000 - Length <= 0x7) { 
    return EFI_INVALID_PARAMETER; 
    } 
    Length  = (UINT16)((Length + 0x7) & (~0x7)); 
    ... 

我沒有得到什麼,我們用下面的操作實現:

Length  = (UINT16)((Length + 0x7) & (~0x7)); 

我知道的長度將是16位對齊。但是我們爲什麼要與全零進行AND?據我瞭解,我們將失去操作中的LSB 3位。這個操作有什麼用?

+3

寫下紙上的「方程」,並解決它的一些隨機值「長度」,看看他們成了什麼。 –

+0

我得到8的倍數。對於長度= 2,1000爲00000000,對於長度= 21等。 – achoora

+0

全部大寫名稱通常僅用於宏。你應該重新考慮你的命名約定。並且不要將固定寬度類型的自制軟件名稱使用。使用'stdint.h'。 – Olaf

回答

3

Length = (UINT16)((Length + 0x7) & (~0x7));

操作執行兩個顯著步驟:

  • 執行的Length
  • 較低的三個比特上方的上舍入通過進位位保證了低三位然後是空的,從而使得結果的8的最接近倍數等於或大於原始值Length

1部分:圍捕

如果Length的低三位,無論如何亮(任何除了000),由0x7111二進制)的增量將通過進位位傳播高於下三個。對於較低三位中的000,較低的三位簡單地變爲111並且沒有進位。例如:

5 - 00000101 
7 - 00000111 
============= 
12 - 00001100 
     ^-------note carry 

又如:

250 - 11111010 
    7 - 00000111 
=============== 
257 - 100000001 

最後,一個例子已經在低三位清晰(並且因此是8的倍數):

24 - 00011000 
7 - 00000111 
============= 
31 - 00011111 

第2部分:剔除下位

一旦值向上舍入,較低的三個比特被剔除,以確保最終的結果是8的倍數使用我們

5 - 00000101 
+ 7 - 00000111 
=============== 
    12 - 00001100 
& ~7 - 11111000 
=============== 
    8 00001000 

接着例如

250 - 11111010 
+ 7 - 00000111 
================ 
257 - 100000001 
& ~7 - 111111000 
================ 
256 - 100000000 

和之前所具有的實例我們的最後一個例子:

24 - 00011000 
+ 7 - 00000111 
=============== 
    31 - 00011111 
& ~7 - 11111000 
=============== 
    24 - 00011000 

總之,本簡單地設置Length是最接近的值相等或高於所述當前值是8的倍數。而已。

+0

幾乎聽起來像是「找到下一個邏輯扇區」例程。 –