防止将数据段使用(优化副本)到本地堆栈数据结构/阵列

时间:2019-03-06 15:50:01

标签: c gcc optimization embedded

我正在编写一些固件,需要使用C代码而不使用数据部分。假设人们远离全局变量,这是非常简单的。还是我想。

我写了一些功能类似于下面的代码:

void func()
{
    int feature_set[][2] = {
        {feature0, 1},
        {feature1, 0},
        {feature2, 0}
    };

    //Use 'feature_set' for some hardware init
}

在我的特定用例中,feature_set是指一些我需要用于初始化的配置数据。因为我是在堆栈上创建此数据集,所以我期望在使用之前先在堆栈上构造它。我意识到这会创建更多的指令,但是在这种情况下我可以选择这样做。

但是,看完反汇编后,我意识到它实际上是在做这样的事情:

mov ecx, <size>
lea edi, <stack addr>
lea esi, <somewhere in .data>
rep movs

很明显,编译器试图通过在.data中创建结构的const版本并在需要时将其复制到堆栈中来优化此操作。

问题:有没有办法防止这种情况?有没有办法告诉编译器不要将数据段用于此操作?更改优化级别可能会起作用,但是我 do 希望进行优化工作……只是不是专门针对这种构造。

1 个答案:

答案 0 :(得分:6)

初始化器列表必须存储在某个地方,您不能随意分配它。通常,初始化列表在.text / .rodata中。然后,编译器可以通过将feature_set(而不是堆栈)放置在.data中来优化初始化,以更快地进行初始化。

无论如何,您可以改为这样做:

static const uint32_t FEATURE_SET [][2] = 
{
  {feature0, 1},
  {feature1, 0},
  {feature2, 0}
};

现在,应将阵列放入闪存(.rodata或类似的存储器)中,否则链接器设置中的某些内容会混乱。

然后在堆栈上需要可修改的运行时版本:

uint32_t feature_set [ sizeof(FEATURE_SET) / sizeof(*FEATURE_SET) ] [2];
memcpy(feature_set, FEATURE_SET, sizeof feature_set);

还要确保不要使用任何怪异的RAM调试版本,而无论调试还是发布版本,都应始终将程序下载到闪存中。