Assembly Bochs GDT段限制在十六进制中向左移动3次,并添加0xFFF。这正常吗?
我目前正在为我的引导加载程序设置GDT。我有3(4)部分:Assembly Bochs GDT段限制在十六进制中向左移动3次,并添加0xFFF。这正常吗?,assembly,x86,osdev,bochs,gdt,Assembly,X86,Osdev,Bochs,Gdt,我目前正在为我的引导加载程序设置GDT。我有3(4)部分: (零段) 4GB内核代码段 4GB内核数据段 2GB堆栈数据部分(我在截图时忘了将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
- (零段)
- 4GB内核代码段
- 4GB内核数据段
- 2GB堆栈数据部分(我在截图时忘了将1位设置为0。稍后这将是1mb)
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粒度。根据第5.3节限制检查: 当G标志清除(字节粒度)时,有效限制为段中20位限制字段的值 描述符。在这里,限制范围从0到FFF H(1兆字节)设置G标志时(4-KByte页面粒度), 处理器将限制字段中的值按2^12(4千字节)的系数进行缩放。。在这种情况下,有效极限范围 从FFFH(4千字节)到FFFFFFH(4千字节)。请注意,当使用缩放(设置了G标志)时 未对照限制检查段偏移量(地址);例如,请注意,如果段限制为0, 偏移量0到FFFH仍然有效 从中,LSL指令描述了所使用的机制,并描述了您在BOCHS中看到的行为: 段限制是一个20位的值,包含在段的字节0和1以及字节6的前4位中 描述符。如果描述符具有字节粒度段限制(粒度标志设置为0),则目标 使用字节粒度值(字节限制)加载操作数如果描述符有页面粒度段限制( 粒度标志设置为1),LSL指令将页面粒度限制(页面限制)转换为字节限制 在将其加载到目标操作数之前通过将20位“原始”限制向左移动12来执行转换 位,并用1填充低位12位。
当我选择0xFF作为4kb粒度的大小时,您问了这样一个问题:这会扩展到0xFFFFF吗,所以我只能使段1mb-1字节大。对于页面粒度,0xFF段限制向左移动12位,产生0xFF000,低12位设置为1。结果是0xFFFFF字节的实际限制。此限制允许从指定的基址寻址满1MiB的内存,即0到0xFFFFF(包括0xFFFFF)。如果希望段具有特定的字节大小(介于0x00000和0xFFFFF之间),可以使用字节粒度。可以用不同的粒度定义描述符。这实际上是限制,而不是大小。但是是的,这是因为页面粒度。