use*_*159 4 c bit-manipulation
我正在阅读Multiboot2规范.你可以在这里找到它.与之前的版本相比,它将所有结构命名为"标签".它们的定义如下:
3.1.3一般标签结构
标签构成了一个缓冲的结构,它们在
u_virt大小上相互填充.每个结构都有以下格式:+-------------------+ u16 | type | u16 | flags | u32 | size | +-------------------+
type分为两部分.Lower包含标签其余部分的内容标识符.size包含标记的大小,包括标题字段.如果设置0了flags(也称为optional)位,如果bootloader缺少相关支持则可能忽略此标记.标签由类型0和大小的 标签终止8.
然后在示例代码中:
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)))
Run Code Online (Sandbox Code Playgroud)
最后一部分让我困惑.在多重引导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
Run Code Online (Sandbox Code Playgroud)
表达式~7取值7并反转所有位.所以:
00010111 // 23 (from pervious step)
&11111000 // bitwise-AND ~7
--------
00010000 // results in 16
Run Code Online (Sandbox Code Playgroud)
现在假设size是17:
00010001 // 17 in binary
+00000111 // add 7
--------
00011000 // results in 24
Run Code Online (Sandbox Code Playgroud)
然后:
00011000 // 24 (from pervious step)
&11111000 // bitwise-AND ~7
--------
00011000 // results in 24
Run Code Online (Sandbox Code Playgroud)
因此,如果低3位size全部为零,即8的倍数,则(size+7)&~7设置这些位然后清除它们,因此没有净效应.但是,如果这些位中的任何一个为1,则对应于8的位递增,则低位被清除,即该数字向上舍入到最接近的8的倍数.