【问题标题】:Initializing a pointer with an absolute memory address用绝对内存地址初始化指针
【发布时间】:2011-10-31 02:54:27
【问题描述】:

我正在我正在处理的自定义操作系统项目中实现 puts(在屏幕上打印字符串)系统调用。字符串的绝对内存地址由代表esi 寄存器的unsigned int 变量提供给我,我需要初始化一个指向unsigned char 数组的指针以从中读取字符串。

寄存器内容表示为:

struct regs
{
    unsigned int gs, fs, es, ds;
    unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
    unsigned int int_no, err_code;
    unsigned int eip, cs, eflags, useresp, ss;
};

我尝试了以下方法来初始化指向esi 中地址的指针:

void fault_handler(struct regs *r) {
   void *p = (void*)r->esi;
   unsigned char* s = (unsigned char*)p;
   // take s and print it to the screen
}

但我没有得到我应该得到的“Hello\n”,而是得到了垃圾。我验证了esi 的地址确实指向了正确的字符串。我的问题是初始化一个指向这个地址的指针。

谢谢!

更新:我将关闭此问题并将讨论转移到一个新问题,因为原始答案已得到回答。谢谢大家!

【问题讨论】:

  • 您确定您的打印模块工作正常吗?
  • 是的。当我将程序图像加载到内存时,我使用相同的代码正确打印了字符串。所以我确定字符串在那里并且打印效果很好。
  • Erm,因此当程序映像加载到内存时,此操作会失败。这究竟意味着什么?通常,您必须在内存中有一些东西才能使指针工作。
  • @The Tuvias :“......我使用相同的代码正确打印了字符串”呃......但你刚刚说这个代码不能正常工作。那么它是否有效?如果代码功能取决于其他一些因素(有时有效,有时无效),那么也许您应该先看看这些其他因素?

标签: c memory operating-system system-calls


【解决方案1】:

您的代码正确地将 esi 分配给 p,然后分配给 s。因此,我只能假设您的问题实际上与此步骤无关。

顺便说一句,我不明白为什么需要 p,只需将 esi 直接分配给 s。

【讨论】:

    【解决方案2】:

    这段代码没问题,正如@David Heffernan 所说,p 没有用处。您可以直接将esi 分配给s。您已经检查了地址,但请检查段寄存器值(实模式)/段选择器(保护模式),确保段寄存器值正确且esi中的地址与在同一段中时使用处理程序,以及描述字符串的位置。可能这会有所帮助。

    【讨论】:

    • 在我的系统调用处理程序中,我得到所有寄存器值,我看到 ss 是 0x1。如果我正确理解了您的评论,您建议我在将字符串加载到内存时检查 ss 的值。如何检查那里使用了哪个段选择器?
    • 将 ss 的内容传输到内存中并检查,但我认为您必须自己分配选择器。你设置了多少段选择器?它们的内存范围是否不同?
    • 我设置了 2 个段 - 一个用于代码,一个用于数据,范围从 0x0 到 0xFFFFFFFF。当我的内核将程序映像加载到内存和我的系统调用处理程序中时,我检查了 cs、ds、es、fs 和 gs,它们是相同的。 ss 是不同的,但我认为这没关系,因为每个任务(内核和用户程序)都有不同的堆栈,不是吗?
    • 重点是你存储字符串的段有一些地址,你需要使用相同的段和偏移地址来取回存储的数据,因为分段后硬件会生成对于具有相同偏移值的每个不同段,分段处理后的不同物理地址。在从内核空间向用户空间发送一些信息的情况下,我认为你应该复制用户空间中的信息并访问用户空间中复制的内容。
    • 你说你有一个代码和一个数据段每个覆盖整个4G内存,你告诉ss不同,ss有什么不同的值?检查ss中的选择器选择哪个段描述符。
    【解决方案3】:

    正如其他人已经指出的那样,您可以立即使用r->esi 初始化s,而无需中间变量p。虽然需要强制转换,所以初始化应该看起来像 unsigned char* s = (unsigned char *) r->esi;

    但是,关于您的代码的某些事情会引起轻微的怀疑。寄存器名称看起来像 x86 平台上的 32 位寄存器的名称。你的指针也是32位的吗? IE。您是否将代码编译为 32 位代码?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-30
      • 2018-04-22
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 2020-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多