【发布时间】: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 程序....