我正在阅读multiboot2规范。你可以找到它here。与前一版本相比,它将所有结构命名为“tags”。它们的定义如下:
3.1.3通用标签结构
标签构成一个结构缓冲区,在u_virt大小上互相填充。每个结构都有
以下格式:

    +-------------------+
u16 | type              |
u16 | flags             |
u32 | size              |
    +-------------------+

type is divided into 2 parts. Lower contains an identifier of contents of the rest of the tag. size contains the size of tag including header fields. If bit 0 of flags (also known as optional) is set if bootloader may ignore this tag if it lacks relevant support. Tags are terminated by a tag of type 0 and size 8.

Then later in example code:

for (tag = (struct multiboot_tag *) (addr + 8);
     tag->type != MULTIBOOT_TAG_TYPE_END;
     tag = (struct multiboot_tag *) ((multiboot_uint8_t *) tag
     + ((tag->size + 7) & ~7)))

最后一部分使我困惑。在multiboot 1中,代码非常简单,您只需执行multiboot_some_structure * mss = (multiboot_some_structure *) mbi->some_addr并直接获取成员,而不会像这样混淆代码。
有人能解释一下((tag->size + 7) & ~7)是什么意思吗?

最佳答案

正如chux在他的评论中所提到的,这将tag->size舍入到8的最接近倍数。
让我们仔细看看它是如何工作的。
假设size是16:

 00010000         // 16 in binary
+00000111         // add 7
 --------
 00010111         // results in 23

表达式~7接受值7并反转所有位。所以:
 00010111         // 23 (from pervious step)
&11111000         // bitwise-AND ~7
 --------
 00010000         // results in 16

现在假设size是17:
 00010001         // 17 in binary
+00000111         // add 7
 --------
 00011000         // results in 24

然后:
 00011000         // 24 (from pervious step)
&11111000         // bitwise-AND ~7
 --------
 00011000         // results in 24

因此,如果size的低3位都为零,即8的倍数,(size+7)&~7设置这些位,然后清除它们,因此没有净效果。但是,如果这些位中的任何一个是1,则对应于8的位被递增,则较低的位被清除,即数字被四舍五入到8的最接近倍数。

08-27 22:06
查看更多