Bochs GDT 段限制以十六进制左移 3 次并添加 0xFFF。这是正常的吗?
Bochs GDT Segment limit is shifted left 3 times in hex and 0xFFF is added. Is this normal?
我目前正在为我的引导加载程序设置 GDT。我有 3 (4) 个细分市场:
- (零段)
- 4GB内核代码段
- 4GB内核数据段
- 2GB Stack Data部分(我截图的时候忘了把1位设置为0,以后就是1mb)
这是我设置 GDT 的代码:
7 ; GDT null segment
8 gdt_null:
9 dq 0x00
10
11 ; GDT code segment (4GB)
12 gdt_code:
13 dw 0xFFFF
14 dw 0x00
15 db 0x00
16 db 10011010b
17 db 11001111b
18 db 0x00
19
20 ; GDT data segment (4GB)
21 gdt_data:
22 dw 0xFFFF
23 dw 0x00
24 db 0x00
25 db 10010010b
26 db 11001111b
27 db 0x00
28
29 ; Extra segmet for stack
30 ; Preventing bufferoverflows from stack could write into other data
31 ; Size is 1M (0x100 * 4kb) startting from base 7e00 (512 bytes after 7c00)
32 gdt_stack:
33 dw 0x0100
34 dw 0x7e00
35 db 0x00
36 db 10010010b
37 db 11001000b
38 db 0x00
但是当我将二进制文件加载到 bochs 中时,它给出了以下结果:
字节完全按照我定义的方式加载到内存中:
这里我意识到0xFFF每次都添加到一个段。是因为我用了4kb的粒度吗?
当我选择 0xFF 作为 4kb 粒度的大小时,这将扩展为 0xFFFFF,所以我只能使段 1mb - 1 字节大?
是的,因为你在GDT条目中使用了4kb的粒度。来自 Intel® 64 and IA-32 Architectures Developer's Manual: Vol. 3A 关于 5.3 限制检查:
When the G flag is clear (byte granularity), the effective limit is the value of the 20-bit limit field in the segment
descriptor. Here, the limit ranges from 0 to FFFFFH (1 MByte). When the G flag is set (4-KByte page granularity),
the processor scales the value in the limit field by a factor of 2^12 (4 KBytes). In this case, the effective limit ranges
from FFFH (4 KBytes) to FFFFFFFFH (4 GBytes). Note that when scaling is used (G flag is set), the lower 12 bits of
a segment offset (address) are not checked against the limit; for example, note that if the segment limit is 0,
offsets 0 through FFFH are still valid.
来自 Intel® 64 and IA-32 Architectures Developer's Manual: Vol. 2A 的 LSL 指令描述了所使用的机制并描述了您在 BOCHS 中看到的行为:
The segment limit is a 20-bit value contained in bytes 0 and 1 and in the first 4 bits of byte 6 of the segment
descriptor. If the descriptor has a byte granular segment limit (the granularity flag is set to 0), the destination
operand is loaded with a byte granular value (byte limit). If the descriptor has a page granular segment limit (the
granularity flag is set to 1), the LSL instruction will translate the page granular limit (page limit) into a byte limit
before loading it into the destination operand. The translation is performed by shifting the 20-bit “raw” limit left 12
bits and filling the low-order 12 bits with 1s.
你问了这个问题当我选择 0xFF 作为 4kb 粒度的大小时,这将扩展到 0xFFFFF,所以我只能使段 1mb - 1 字节大?。对于页面粒度,0xFF 段限制向左移动 12 位产生 0xFF000,低 12 位设置为 1。结果是 0xFFFFF 字节的实际限制。此限制允许寻址从指定基数开始的 0 到 0xFFFFF(含)的完整 1MiB 内存。如果您希望段具有特定的字节大小(介于 0x00000 和 0xFFFFF 之间),您可以使用字节粒度。可以使用不同的粒度定义描述符。
我目前正在为我的引导加载程序设置 GDT。我有 3 (4) 个细分市场:
- (零段)
- 4GB内核代码段
- 4GB内核数据段
- 2GB Stack Data部分(我截图的时候忘了把1位设置为0,以后就是1mb)
这是我设置 GDT 的代码:
7 ; GDT null segment
8 gdt_null:
9 dq 0x00
10
11 ; GDT code segment (4GB)
12 gdt_code:
13 dw 0xFFFF
14 dw 0x00
15 db 0x00
16 db 10011010b
17 db 11001111b
18 db 0x00
19
20 ; GDT data segment (4GB)
21 gdt_data:
22 dw 0xFFFF
23 dw 0x00
24 db 0x00
25 db 10010010b
26 db 11001111b
27 db 0x00
28
29 ; Extra segmet for stack
30 ; Preventing bufferoverflows from stack could write into other data
31 ; Size is 1M (0x100 * 4kb) startting from base 7e00 (512 bytes after 7c00)
32 gdt_stack:
33 dw 0x0100
34 dw 0x7e00
35 db 0x00
36 db 10010010b
37 db 11001000b
38 db 0x00
但是当我将二进制文件加载到 bochs 中时,它给出了以下结果:
字节完全按照我定义的方式加载到内存中:
这里我意识到0xFFF每次都添加到一个段。是因为我用了4kb的粒度吗?
当我选择 0xFF 作为 4kb 粒度的大小时,这将扩展为 0xFFFFF,所以我只能使段 1mb - 1 字节大?
是的,因为你在GDT条目中使用了4kb的粒度。来自 Intel® 64 and IA-32 Architectures Developer's Manual: Vol. 3A 关于 5.3 限制检查:
When the G flag is clear (byte granularity), the effective limit is the value of the 20-bit limit field in the segment descriptor. Here, the limit ranges from 0 to FFFFFH (1 MByte). When the G flag is set (4-KByte page granularity), the processor scales the value in the limit field by a factor of 2^12 (4 KBytes). In this case, the effective limit ranges from FFFH (4 KBytes) to FFFFFFFFH (4 GBytes). Note that when scaling is used (G flag is set), the lower 12 bits of a segment offset (address) are not checked against the limit; for example, note that if the segment limit is 0, offsets 0 through FFFH are still valid.
来自 Intel® 64 and IA-32 Architectures Developer's Manual: Vol. 2A 的 LSL 指令描述了所使用的机制并描述了您在 BOCHS 中看到的行为:
The segment limit is a 20-bit value contained in bytes 0 and 1 and in the first 4 bits of byte 6 of the segment descriptor. If the descriptor has a byte granular segment limit (the granularity flag is set to 0), the destination operand is loaded with a byte granular value (byte limit). If the descriptor has a page granular segment limit (the granularity flag is set to 1), the LSL instruction will translate the page granular limit (page limit) into a byte limit before loading it into the destination operand. The translation is performed by shifting the 20-bit “raw” limit left 12 bits and filling the low-order 12 bits with 1s.
你问了这个问题当我选择 0xFF 作为 4kb 粒度的大小时,这将扩展到 0xFFFFF,所以我只能使段 1mb - 1 字节大?。对于页面粒度,0xFF 段限制向左移动 12 位产生 0xFF000,低 12 位设置为 1。结果是 0xFFFFF 字节的实际限制。此限制允许寻址从指定基数开始的 0 到 0xFFFFF(含)的完整 1MiB 内存。如果您希望段具有特定的字节大小(介于 0x00000 和 0xFFFFF 之间),您可以使用字节粒度。可以使用不同的粒度定义描述符。