【问题标题】:How to directly access a memory address without using a pointer?如何不使用指针直接访问内存地址?
【发布时间】:2017-10-31 23:01:50
【问题描述】:

下面是我的代码。 请注意,我不是在普通机器上运行此代码,而是在架构模拟器 (gem5) 上运行。

#include <stdio.h>
int main() 
{
   int *p;
   int x;
   p = &x;
   p[0] = 3;
   // *(0xffff) = 6;
   return 0;
}

如果我取消注释该行,我会收到一个编译器错误(这是预期的)“间接需要指针操作数”。 由于我不是在实际机器上运行它,而是在模拟器上运行它,因此我可以控制硬件的行为方式和地址空间。 我想将值 6 存储在地址 0xffff 中。一种方法是:

int *p;
p = (int *)0xffff;
p[0] = 6;

请注意,这不会导致分段错误,因为我在模拟器上运行它,并且我控制地址空间。 但是,这是一种低效的方法,因为每次应该访问变量“p”时,获取 0xffff,然后存储 6。访问变量“p”即使声明为寄存器,也需要 1 个周期,从长远来看,这对我来说代价高昂跑。 因为我知道'p'总是有0xffff,我不能写类似的东西

*(0xffff) = 3;

如何让编译器生成此代码? 任何指针都会有所帮助。

【问题讨论】:

  • 正如你所说,“任何指针都会有所帮助
  • 这本身不是 C 问题,而是操作系统问题和虚拟内存管理器问题。现代操作系统不允许实模式内存访问。 (允许某些 API 用于专用硬件、图形等。)但是从安全计算的角度来看,过去二十年的进步旨在完全防止这种类型的直接访问,而支持与硬件交互的保护模式API而不是硬件。您可以在模拟器中设置Real mode 以及用户空间寻址的开始位置吗?
  • 启用优化的编译器将尽可能避免存储p 变量的值。除非您已经看过生成的程序集并且知道有更好的方法,否则您不应该执行此类微优化。
  • @David C. Rankin 现在所有程序都在托管环境中运行。我的 99% 没有(我主要做裸机嵌入式项目)。
  • 是的,我看到了需求和好处,尤其是对于嵌入式系统。具有讽刺意味的是,随着软件开始在越来越多的设备上运行并服务于不同的目的,人们花费了多少努力来阻止实模式寻址只是为了找到重新出现的需求。不久前,您必须将打孔卡洗牌到读卡器中才能运行 FORTRAN 程序....

标签: c pointers


【解决方案1】:

我不知道你是否可以在没有指针的情况下做到这一点,但如果你不想在单独的行上声明一个指针,你可以这样做:

*(int*)(0xffff) = 3;

【讨论】:

  • 我很快就会在模拟器上运行它,如果它需要额外的周期并报告。谢谢。
【解决方案2】:

如果您担心额外的循环,您可以使用一些内联汇编。通常,MOV 指令 (MOV r/m32, imm32) 允许您将立即数移入寄存器,或移入寄存器指向的地址。如果你想完全绕过寄存器的使用,你可以使用C6指令(from this post)。

  c6        04         25      0xffff     3
  opcode    modr/m     sib     address    immediate

假设您使用的是 x86 架构,您可以在源文件的内联汇编中包含该指令。

【讨论】:

  • 一个体面的优化编译器会自动使用最佳指令来完成这项工作。没有理由为此使用内联汇编。
  • 你说得对,我不知道直接做这么容易。
猜你喜欢
  • 1970-01-01
  • 2019-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-16
  • 1970-01-01
  • 2013-12-22
  • 1970-01-01
相关资源
最近更新 更多