问题标签 [memory-segmentation]

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.

0 投票
6 回答
97128 浏览

assembly - “FS”/“GS”寄存器的用途是什么?

所以我知道以下寄存器及其用途应该是什么:

  • CS = 代码段(用于 IP)

  • DS = 数据段(用于 MOV)

  • ES = Destination Segment(用于MOVS等)

  • SS = 堆栈段(用于 SP)

但是以下寄存器的用途是什么?

  • FS =“文件段”?

  • GS = ???

注意:我不是在询问任何特定的操作系统——我是在询问它们打算被 CPU 用于什么,如果有的话。

0 投票
2 回答
9554 浏览

assembly - 操作码中的汇编段

我注意到在程序集段中使用了操作码。

例子:

我认为“PTR SS:”用于指定 EBP-30 来自堆栈?(SS:堆栈段)我是对的还是完全错的?:) 而且,你能告诉我上面的例子和

那么操作码中使用的 DS(数据段)呢?

0 投票
3 回答
1920 浏览

linux - 分段寄存器使用

我试图了解内存管理是如何在低级别进行的,并且有几个问题。

1) Kip R. Irvine 的一本关于汇编语言的书说,在实模式下,程序启动时,前三个段寄存器加载了代码、数据和堆栈段的基地址。这对我来说有点模棱两可。这些值是手动指定的,还是汇编器生成指令将值写入寄存器?如果它自动发生,它如何找出这些段的大小?

2)我知道Linux使用扁平线性模型,即以非常有限的方式使用分段。此外,根据 Daniel P. Bovet 和 Marco Cesati 的“Understanding the Linux Kernel”,GDT 中有四个主要部分:用户数据、用户代码、内核数据和内核代码。所有四个段都具有相同的大小和基地址。如果它们仅在类型和访问权限上有所不同(它们都产生相同的线性地址,对吗?),我不明白为什么需要其中四个。为什么不只使用其中一个并将其描述符写入所有段寄存器?

3)不使用分段的操作系统如何将程序划分为逻辑段?例如,它们如何区分堆栈和没有段描述符的代码。我读到分页可用于处理此类事情,但不明白如何。

0 投票
3 回答
1007 浏览

c++ - Visual Studio 2010 - 数据段和堆栈内存相同

我发现一个常量文字 get 放置在程序的数据段中(来自 SO)并且是只读的,因此“s[0] = 'a'”行会导致错误,这实际上发生在我取消注释该行并运行。但是,当我查看 MS VS 中的内存窗口时,变量都放在内存中。我很好奇他们(编译器)如何强制对“s”进行只读访问?

编辑 1:更新存储在 s_arr 中的值(应放置在堆栈空间中),以明确它与字符串常量相邻放置。

编辑 2:由于我看到有关基于页面的 ro/rw 访问的答案,这里地址 .. 0x...4f4 是 rw 0x...4fc 是ro并且 0x...504 是 rw。他们如何实现这种粒度?此外,由于每个页面可能至少为 4kb,因此有人可能会争辩说 0x4fb 可能是前一个 ro 页面的最后地址。但是我现在添加了一些变量,以表明它们都连续放置在内存中,并且粒度是每 8 个字节。您可以说,由于您提到的页面处于 4k 级别,

0 投票
1 回答
4505 浏览

assembly - linux x86 64 中 MSR_GS_BASE 的详细信息

我试图找出 Linux 内核中当前 MACRO 的详细信息。current的最终汇编代码为:

上面的代码可以工作!但是当我打印 %%gs 时,它的值为 0,所以 %%gs 指向 GDT NULL 的第一项!!??这个怎么运作?

相反,gs 的基数在 MSR_GS_BASE 中,当前可以替换为:

我的问题是:

%gs 指向 GDT NULL 的第一项!!?? 从 MSR_GS_BASE 读取它是如何工作的,它是 CPU 特性吗?我需要一些关于此的参考。

0 投票
2 回答
1394 浏览

x86 - 为小内核设计 GDT

我目前正在编写一些小的内核代码。以下是我从某处的内核项目中复制的内容。它包含将内核加载到内存位置 0x1000 并跳转到位置 0x1000 的代码:

以下在 GDT.INC 中:

以上工作了很长时间。然而,当我的内核开始变大时,数据和代码段重叠了。虽然两者都从 0 开始,但数据段中的数据与代码段中的代码或类似内容重叠。因此,我无法完全打印消息。

有没有办法改变数据段和代码段的基址,以便在基址之间有一些空间来编写一个最大约为 1 MB 的二进制小内核?

我已将链接附加到内核并在下面详细描述问题:

  1. 我使用以下方法制作内核:

    /li>

在 src 文件夹内

  1. 使用以下命令在 qemu 中启动它:

    /li>
  2. 启动后,我运行以下命令来验证字符串操作:

    /li>
  3. 然后我运行以下命令,我看到消息在中间被剥离并且在某一行之后没有打印:

    /li>
  4. 如果我在 console.c 中注释以下行并运行 pcnetops,我会打印所有内容:

    /li>

这就是为什么我怀疑我是否应该将代码段和数据段基地址分开的原因(现在两者都是 0)

0 投票
4 回答
5412 浏览

assembly - 在汇编语言中更改 CS:IP

你怎么能强行改变汇编语言CSIP

ORG指令可以用来改变数字的IP,但是你怎么改变CS呢?

基本上我想用汇编来实现多线程。

许多论坛,包括堆栈溢出中的一个问题都说这是不可能的,但是即使 C 是由汇编代码制成的,它又如何具有多线程选项呢?

0 投票
1 回答
1388 浏览

process - 虚拟内存概念

我对有关虚拟内存的一些主题感到困惑。所以,我将逐点列出它们并提出问题。在回答时,如果您还列出一些我可以消除疑问的来源,我会更喜欢。我将参考 linux elf 可执行文件进行讨论。

  1. 我听说在 32 位系统中每个进程都有 4gb 的地址空间。当我检查我的一个可执行可重定位文件的 objdump 时,我看到它的限制从 00000000 到 ffffffff。它还包含内核空间。这是文件的地址空间。这就是我们说的虚拟内存吗?如果是,那么我已经读过虚拟内存机制允许运行非常大的进程,并且进程大小不受主内存大小的限制(我们可以在按需分页时将所需的页面带到主内存)。那么如果虚拟内存只有4gb,是不是限制程序的最大大小为4gb呢?此外,我检查了另一个文件的 objdump,它具有相同的地址(即 00000000 到 ffffffff)。那么这是什么意思?这是否意味着我们的文件是某种可重定位文件,将再次添加起始地址(尽管这看起来很荒谬,因为它已经是一个可执行的可重定位目标文件)。

  2. 我读过在已实现分段的内存中,cpu 产生虚拟(逻辑)地址。这个地址包含三个部分——段,段内的偏移量。此外,这里讨论的部分是代码、数据、堆栈等。

    在进程地址空间中,这些段从特定位置开始定位。那么,cpu的虚拟地址的内容是什么?生成的虚拟地址范围是否从 00000000 到 ffffffff?如果是,那么是在虚拟地址访问内容的过程,如下:-

    这再次出现了这样一个事实,即任何时候都没有进程可以完全位于主内存中,因为这样整个内存将只被一个进程占用(因为进程的地址空间本身就是 4gb)。

    此外,如果所有进程的地址空间从 00000000 到 ffffffff,并且主内存中一次可以存在多个进程,那么所有进程都应该有自己的段描述符表,该表返回线性地址空间中的段地址

  3. 我读到操作系统在启动时被加载到主内存中。那么该操作系统与特定进程的内核空间中的内核代码有什么区别?此外,是否所有进程在其内核空间中都有自己的内核代码副本?
0 投票
2 回答
660 浏览

x86 - x86 数据段在实际操作系统和进程中是如何使用的?

我一直在实模式下编写 x86 asm 程序(引导加载程序),并且我知道如何使用段、寄存器和类似的东西。

我从 OllyDbg 之类的调试器和类似的调试器中看到 DS 寄存器、SS 等……显然被使用了……但是普通的“类似 Windows”的进程如何使用它们呢?我知道分段被部分使用(只是为了将 ring0 与 ring3 分开)并且它们的条目在 GDT 中,我知道这涉及到分页,这会完全混淆 PDE 和 PTE 的地址,但我不能完全“链接” 将所有内容放在一起并了解数据堆栈额外段的全部内容。每个进程是否有不同的 DS/SS/ES?

0 投票
1 回答
247 浏览

c - 设置数据段后访问 GDT?

这是一个非常愚蠢的问题,但我似乎无法解决它。在我的操作系统中,GDT 是通过与内核链接的汇编代码设置的。发生这种情况时,当然数据段和代码段是在加载 GDT 时设置的。此信息存储在汇编代码中为

所有段都设置得很好,但是我无法通过指向 GDT_Contents 的指针访问 GDT。我已经测试了几种方法,主要是通过创建一个指向 0(即 GDT_Contents 的位置)的指针并回显它们的字节。它们与 GDT_Contents 不匹配。我很确定这是因为当 GDT 被加载时,它是相对于先前的数据段(0x0 或由引导加载程序设置的,我不确定)。但无论如何,我现在不知道如何访问 GDT,我想设置 TSS,我不能将其硬编码到 GDT_Contents 中,因为它需要指向我的 TSS 结构的指针。我认为这就像恢复以前的数据段一样容易,但我不知道该怎么做。这是设置 GDT 的汇编代码

当然,这是 32 位保护模式下的 x86。