我正在阅读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的最接近倍数。