(size + 7) & ~7 是什么意思?
What does (size + 7) & ~7 mean?
我正在阅读 Multiboot2 规范。你可以找到它here。与之前的版本相比,它命名了所有的结构"tags"。它们的定义如下:
3.1.3 General tag structure
Tags constitutes a buffer of structures following each other padded on u_virt
size. Every structure has
following format:
+-------------------+
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
.
然后在示例代码中:
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)
是什么意思?
& ~7
将最后三位设置为 0
正如 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 的倍数。
~ 有点不是。 & 是按位与
假设使用 16 位:
7 is 0000 0000 0000 0111
~7 is 1111 1111 1111 1000
任何带0的and'都是0。任何带1的and'都是它本身。于是
N & 0 = 0
N & 1 = N
因此,当您与 ~7 进行 AND 运算时,您基本上清除了最低的三位,而所有其他位保持不变。
感谢@chux 的回答。根据他的说法,如果需要,它会将 size
向上舍入为 8 的倍数。这与 15bpp 绘图代码中完成的技术非常相似:
//+7/8 will cause this to round up...
uint32_t vbe_bytes_per_pixel = (vbe_bits_per_pixel + 7) / 8;
推理如下:
Things were pretty simple up to now but some confusion is introduced
by the 16bpp format. It's actually 15bpp since the default format is
actually RGB 5:5:5 with the top bit of each u_int16 being unused. In
this format, each of the red, green and blue colour components is
represented by a 5 bit number giving 32 different levels of each and
32786 possible different colours in total (true 16bpp would be RGB
5:6:5 where there are 65536 possible colours). No palette is used for
16bpp RGB images - the red, green and blue values in the pixel are
used to define the colours directly.
我正在阅读 Multiboot2 规范。你可以找到它here。与之前的版本相比,它命名了所有的结构"tags"。它们的定义如下:
3.1.3 General tag structure
Tags constitutes a buffer of structures following each other padded on
u_virt
size. Every structure has following format:+-------------------+ 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 bit0
offlags
(also known asoptional
) is set if bootloader may ignore this tag if it lacks relevant support. Tags are terminated by a tag of type0
and size8
.
然后在示例代码中:
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)
是什么意思?
& ~7
将最后三位设置为 0
正如 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 的倍数。
~ 有点不是。 & 是按位与 假设使用 16 位:
7 is 0000 0000 0000 0111
~7 is 1111 1111 1111 1000
任何带0的and'都是0。任何带1的and'都是它本身。于是
N & 0 = 0
N & 1 = N
因此,当您与 ~7 进行 AND 运算时,您基本上清除了最低的三位,而所有其他位保持不变。
感谢@chux 的回答。根据他的说法,如果需要,它会将 size
向上舍入为 8 的倍数。这与 15bpp 绘图代码中完成的技术非常相似:
//+7/8 will cause this to round up...
uint32_t vbe_bytes_per_pixel = (vbe_bits_per_pixel + 7) / 8;
推理如下:
Things were pretty simple up to now but some confusion is introduced by the 16bpp format. It's actually 15bpp since the default format is actually RGB 5:5:5 with the top bit of each u_int16 being unused. In this format, each of the red, green and blue colour components is represented by a 5 bit number giving 32 different levels of each and 32786 possible different colours in total (true 16bpp would be RGB 5:6:5 where there are 65536 possible colours). No palette is used for 16bpp RGB images - the red, green and blue values in the pixel are used to define the colours directly.