gpt4 book ai didi

assembly - 为什么我不能改变段寄存器的值? (MASM)

转载 作者:行者123 更新时间:2023-12-04 06:52:14 27 4
gpt4 key购买 nike

我决定自学汇编语言。

我已经意识到,如果我尝试更改任何段寄存器的值,我的程序将无法编译。

我发现的每篇文章都说我确实可以更改至少 4 个段寄存器的值,那是什么?

我真的只对为什么此时感兴趣,我没有任何真正的目的来改变这些地址。

最佳答案

你说你对为什么感兴趣,所以:

在实模式下,段是物理内存的 64K“窗口”,这些窗口间隔 16 个字节。在保护模式下,段是物理内存或虚拟内存的窗口,其大小和位置由操作系统决定,并且它具有许多其他属性,包括进程必须具有什么权限级别才能访问它。

从这里开始,我所说的一切都是指保护模式。

内存中有一个称为全局描述符表 (GDT) 的表,其中保存了有关这些窗口大小和位置以及其他属性的信息。每个进程也可能有本地描述符表,它们以类似的方式工作,所以我只关注 GDT。

加载到段寄存器中的值称为段选择器。它是 GDT 或 LDT 的索引,带有一些额外的安全信息。自然地,如果程序尝试加载 GDT 边界之外的描述符,则会发生异常。此外,如果进程没有足够的权限访问该段,或者其他无效的内容,则会发生异常。

当异常发生时,内核会处理它。这种异常可能会被归类为段错误。所以操作系统会杀死你的程序。

最后还有一个警告:在 x86 指令集中,您不能将立即值加载到段寄存器中。您必须使用中间寄存器或内存操作数或 POP 到段寄存器中。

MOV DS, 160 ;无效 - 不会组装

MOV AX, 160 ;VALID - 组装,但可能会导致
MOV DS, AX ; 异常,从而导致程序死亡

我认为应该指出的是,该架构允许段堆。但是 AFAIK,当涉及到主流 x86 操作系统时,段寄存器仅用于几个目的:

  • 安全机制,例如防止用户空间进程相互伤害或对操作系统造成伤害
  • 处理多核/多核处理器
  • 线程本地存储:作为优化,一些操作系统(包括 Linux 和 Windows)使用段寄存器进行线程本地存储(TLS)。由于线程共享相同的地址空间,线程很难在不使用系统调用或浪费寄存器的情况下“知道”其 TLS 区域的位置......它们是为了快速 TLS。请注意,在设置时,操作系统可能会跳过段寄存器并直接写入描述符缓存寄存器,这些寄存器是“隐藏”寄存器,用于缓存由对段寄存器的引用触发的 GDT/LDT 查找,在这种情况下,如果您尝试要从段寄存器中读取,您将看不到它。

  • 除了用于 TLS 的每个线程一个段之外,实际上只有少数段(处理器数量的倍)被使用,并且仅由操作系统使用。应用程序可以完全忽略段寄存器。

    这是由于操作系统设计,而不是任何技术限制。可能有嵌入式操作系统需要用户空间程序来处理段寄存器,尽管我不知道。

    关于assembly - 为什么我不能改变段寄存器的值? (MASM),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/125532/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com