2016-12-27 36 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

几乎听起来像是“找到下一个逻辑扇区”例程。 –