Bochs GDT分段限制以十六进制向左移动3次,并添加了0xFFF。这正常吗?

时间:2019-05-03 11:04:27

标签: 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 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中时,会得到以下结果: GDT Image

完全按照我的定义将字节加载到内存中: Memory Image

在这里,我意识到每次将0xFFF添加到段中。这是因为我使用4kb作为粒度吗?

当我选择0xFF作为具有4kb粒度的大小时,它将扩展为0xFFFFF,所以我只能将段设为1mb-1字节大吗?

1 个答案:

答案 0 :(得分:2)

是的,这是因为您在GDT条目中使用了4kb的粒度。来自Intel® 64 and IA-32 Architectures Developer's Manual: Vol. 3A中有关 5.3极限检查

  

清除G标志(字节粒度)时,有效限制为该段中20位限制字段的值   描述符。在此,限制范围是0到FFFFFH(1 MB)。 设置了G标志(4 KB页面粒度)后,   处理器将限制字段中的值缩放2 ^ 12(4 KB)。在这种情况下,有效极限范围   从FFFH(4 KB)到FFFFFFFFH(4 GB)。请注意,使用缩放比例(设置了G标志)时,   段偏移量(地址)不会根据限制进行检查;例如,请注意,如果细分限制为0,   偏移量0到FFFH仍然有效。

Intel® 64 and IA-32 Architectures Developer's Manual: Vol. 2A中, LSL 指令对使用的机制进行了描述,并描述了您在BOCHS中看到的行为:

  

段限制是一个20位的值,包含在该段的字节0和1中以及字节6的前4位中   描述符。如果描述符具有字节粒度段限制(粒度标志设置为0),则目标   操作数加载有字节粒度值(字节限制)。 如果描述符有页面细分范围限制(   粒度标志设置为1),LSL指令会将页面粒度限制(页面限制)转换为字节限制   在将其加载到目标操作数之前。 通过将20位“原始”限制向左移动12来执行翻译   位,并用1s填充低阶12位。

您问的问题当我选择0xFF时,粒度为4kb的大小会扩展为0xFFFFF,所以我只能将段设为1mb-1字节大吗?。使用页面粒度,将0xFF段限制左移12位,产生0xFF000,将低12位设置为1。结果是实际限制为0xFFFFF字节。此限制允许寻址完整的1MiB内存,从指定的基数开始,该内存为0到0xFFFFF(包括0)。如果您希望段具有特定的字节大小(介于0x00000和0xFFFFF之间),则可以使用字节粒度。可以使用不同的粒度定义描述符。