问题标签 [gdt]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
assembly - 如何在 NASM 程序集中进入 32 位保护模式?
我正在学习 x86 汇编,我正在尝试在 NASM 中制作一个玩具操作系统,但我不明白一些东西。
我制作了一个成功启动内核的引导加载程序:
- 从包含内核文件的软盘加载 14 个扇区;
kernel.feo
在这些标记为;的扇区中搜索文件- 将该文件加载到内存中的偏移量
0x2000
; - 使用远跳转执行内核
jmp 0x2000:0x0000
。
所以我的内核代码位于0x2000:0
内存中。CS
由于使用了远跳,可能会正确设置。在这个内核代码中,我想进入 32 位保护模式,但我不确定 GDT 是如何工作的。当我在虚拟机上运行下面的代码时(QEMU)
,它什么也不做。
我想请你帮我进入 32 位保护模式!
也就是说,您有以下问题:
- 您假设代码是
0x7c00:0
由于 加载的org 0
,但情况可能并非如此。唯一保证的是物理地址。您应该使用远跳转到您的入口点,以便CS
正确设置。- 您出于某种原因设置
DS
为,0x2000
因此您的代码根本找不到任何数据。您应该设置DS
为 matchCS
,或在任何地方使用CS
覆盖(不推荐)。- 保护模式代码假定从零开始的段,这反过来意味着它期望
org 0x7c00
这当然与您的设置冲突。您应该切换到org 0x7c00
和 段0
。- VGA 文本模式段为
0xb8000
not0xb80000
(减一)。0x55 0xaa
引导扇区末尾没有引导签名字节。
我在我的代码中更正了这些事情:
[org 0x0]
被更正为[org 0x2000]
,段被设置为0
;DS
被更正为,0
而不是0x2000
,所以现在它匹配CS
;- VGA 文本模式段更正为
0xb8000
;
但是代码无法使用这些更正,它应该打印两个字符串但它什么都不做!
请注意,此内核代码不应以引导签名结尾0x55 0xAA
,因为它不是引导扇区。
这是更正的内核代码(不起作用):
assembly - NASM 如何在没有 org 的情况下设置相对于加载地址的标签地址
我正在尝试为内核编写引导加载程序。目前我正在用程序集加载 GDT,但我想编写一些 C 代码来生成 GDT(和 IDT)问题是引导扇区总是在地址 0x7c00 加载,所以我需要一种方法来抵消我的标签与那个地址。如果我组装成一个 bin 文件,我可以只使用 [org 0x7c00] 但我想将引导加载程序组装成一个目标文件(NASM 不支持这种格式的 org),以便我可以使用外部符号。如果没有 org,我的汇编代码中有这个:
组装后的样子:
什么时候应该
该表本身也是错误的,因为 gdt 起始位置没有考虑偏移量。
除了我自己手动添加偏移量(我必须有很多地方),有没有我可以用来设置起始地址的指令?
编辑:从 0xc700 更改为 0x7c00
x86 - 大实模式下的地址翻译
正如http://wiki.osdev.org/Unreal_Mode所说,我有一些关于地址转换如何在大实模式下发生的问题
虚幻模式包括打破实模式段的“64Kb”限制,但仍通过调整描述符缓存来保持 16 位指令和段*16+偏移地址的形成
但我的问题是如何在过程中使用 gdt,甚至在转换为线性地址时是否使用它。如果有人可以指出切换到大实模式的某些规范或其他参考,那将非常有帮助,如果有人可以提供有关如何切换回实模式的一些见解,那将非常好。
问候,
阿尔卡
linux - 当设置为 TLS 选择器时,为什么 ES 和 DS 最终会在 64 位内核上归零?
下面的 32 位程序调用set_thread_area(2)
在 GDT 中创建一个条目,该条目旨在用于 TLS。通常,生成的选择器会被放入FS
或GS
成功使用。但是,如果它被放入DS
or ES
,在 64 位内核上运行,最终(我猜是在上下文切换之后)这个选择器归零。
但是,如果我改为使用modify_ldt(2)
并将生成的 LDT 条目的选择器放入这些段寄存器中,它们似乎保留了它们的值!
此外,如果我将 64 位代码段 ( 0x33
) 或 32 位代码段 ( 0x23
) 的选择器(它们都引用 GDT)放入DS
or ES
,它们不会被清零。
这是源代码(使用fasm编译),展示了奇怪的行为:
这似乎与 64 位进程默认在这两个段寄存器中具有 NULL 选择器这一事实有关。
这发生在 Linux 3.16.0 及更早版本上,但不会出现在 4.2.0 及更高版本上。
这里发生了什么?为什么在其中包含 TLS 选择器时会清零,但ES
与DS
任何其他选择器无关?
x86 - LDT 和 GDT 在 Intel x86 中的使用方式有何不同?
我知道这两个表都包含段描述符,这些描述符提供了每个段的访问详细信息,包括基地址、类型、长度、访问权限等。
看这篇博客描述的区别如下:
1. GDT 在系统中只有一个副本,而 LDT 可以有很多
2. GDT 在执行过程中可能不会更改,LDT 经常在任务切换时更改
3. LDT 的条目保存在 GDT 中。GDT 和 LDT 中的条目具有相同的结构。
系统在实际程序中如何以不同的方式使用这些结构?
assembly - 在长模式下更改 GDT 并更新 CS
我正在编写一个简单的自制 64 位操作系统,通过 UEFI 启动它。这意味着当我的代码开始执行时,它已经处于长模式,并启用了分页。
现在,在退出 UEFI 引导服务后,我想用我自己的替换 UEFI 构建的所有控制结构。
成功更改 CR3(分页结构)的内容后,我使用lgdt
.
问题是现在,为了正确使用这个新的 GDT,我需要将一个新值移动到 CS 中。在网上我找到了很多关于如何从 32 位切换到 64 位的教程,但几乎没有关于长模式到长模式的内容。
我认为我应该使用远跳,但我没有设法用这段代码(AT&T 语法)做到这一点:
没有任何 IDT,此代码在retfq
.
编辑:我检查了我的分页结构,我很确定它们不是问题的原因。事实上,没有最后三个指令,代码运行良好。问题是我需要一种更新 CS 的方法,在我的代码中仍然指的是 UEFI 构建的旧段。这样做是retfq
正确的方法吗?或者我应该使用哪个其他指令?
提前致谢。
x86 - 如何在 x86 中启用分页并在 UEFI 中显示 GDT
我的目标是在 UEFI 中启用 x86 中的分页。我的教授说,我可能会先尝试在 UEFI 中显示 GDT - 这样我也会查看分页是否有效。问题是,我不知道该怎么做。
我使用本教程在 Visual Studio 中启用 EDK2:http: //uefi.blogspot.com/2013/06/how-to-set-up-edk2s-windows-hosted-uefi.html
你能指点我任何教程或解释我该怎么做吗?
linux - 全局描述符表和本地描述符表的关系?
我正在查看此链接的分段。
LDT 和 GDT 都是独立的还是相互依赖的?
(TI位(这是选择器的一部分)来决定应该使用哪个描述符表(GDT或当前活动的LDT)所以我认为它是独立的)
还有 GDT(全局描述符表),主要用于保存操作系统段的描述符条目。示例内核堆栈--code_section/data_section?
LDT 第二种类型称为 LDT(本地描述符表),包含普通应用程序段的条目(尽管不一定)用户堆栈 --code_section/data_section ?
它说 LDTR 寄存器包含内存中当前活动 LDT 的大小和位置。这是否意味着在上下文切换中我们将每个进程的 LDTR 值保存在该进程的 pcb 中?
assembly - 定义全局描述符表有什么用?
我读了一篇关于 GDT(全局描述符表)的教程,它将 GDT 定义为“为内存的某些部分定义基本访问权限的那个”。这意味着 GDT 用于内存保护。
它是否执行上述以外的任何其他任务?
在操作系统中实现 GDT 是必须的吗?
简而言之,如果有人能以易于理解的方式详细说明 GDT,那就更好了。
谢谢
x86 - 为什么 x86 处理器在 GDT 中需要一个 NULL 描述符?
我在 i386 上编写自己的操作系统,然后是全局描述符表设置,我对 NULL 描述符感到困惑。
在1986 年英特尔 80386 程序员参考手册中,
NULL_DES DESC <> ; 空描述符
是关于 NULL 描述符的唯一提及。
有没有人告诉我为什么 x86 处理器在 GDT 中需要一个 NULL 描述符?