avr-g ++和PC

时间:2016-11-02 08:39:19

标签: c++ avr

我的问题是构造函数/析构函数执行优化:PC和AVR(8位)平台之间的执行顺序存在显着差异。

我创建了一个小源来演示它。重要的部分是C类,它在运算符<(<()。

中实例化

让我们先看看PC版:

(此处的F类仅用于查看输出中的浮点运算)

#include <iostream>
struct C
{
    C()
    {
        std::cout << "C created" << std::endl;
    }
    ~C()
    {
        std::cout << "C deleted" << std::endl;
    }
};
struct D
{
    D & operator<<(float f)
    {
        C _c;
        std::cout << "D << " << f << std::endl;
        value = f;
        return *this;
    }
    float value;
};
struct F
{
    F(float f):
        value(f)
    {
        std::cout << "F created: " << value << std::endl;
    }
    operator float()
    {
        return value;
    }
    F operator+(float f)
    {
        std::cout << value << "+" << f << "=" << value+f << std::endl;
        return F(value+f);
    }
    float value;
};

F f1(3.5f);
F f2(4.2f);
D d;

int main()
{
    std::cout << "main() started" << std::endl;
    d << (f1+f2);
}

我为我的PC编译了它(这个源是在main.cpp中):

g++ -o main -O4 -Wall main.cpp

执行结果如下:

$ ./main 
F created: 3.5
F created: 4.2
main() started
3.5+4.2=7.7
F created: 7.7
C created
D << 7.7
C deleted

执行顺序在这里是正确的,一切都按预期进行。

要为AVR(8位系列)编译它,删除了std :: cout调用,并稍微修改了类C:

struct C
{
    C()
    {
        asm("cli");
    }
    ~C()
    {
        asm("sei");
    }
};
struct D
{
    D & operator<<(float f)
    {
        C _c;
        value = f;
        return *this;
    }
    float value;
};
float f1(3.5f);
float f2(4.2f);
D d;

int main()
{
    d << (f1+f2);
}

它是为AVR(8位系列)编译的:

avr-g++ -o main -O4 -Wall main.cpp

让我们看看主要功能的结果:

00000028 <main>:
  28:   f8 94           cli
  2a:   20 91 68 00     lds r18, 0x0068
  2e:   30 91 69 00     lds r19, 0x0069
  32:   40 91 6a 00     lds r20, 0x006A
  36:   50 91 6b 00     lds r21, 0x006B
  3a:   60 91 64 00     lds r22, 0x0064
  3e:   70 91 65 00     lds r23, 0x0065
  42:   80 91 66 00     lds r24, 0x0066
  46:   90 91 67 00     lds r25, 0x0067
  4a:   2e d0           rcall   .+92        ; 0xa8 <__addsf3>
  4c:   60 93 60 00     sts 0x0060, r22
  50:   70 93 61 00     sts 0x0061, r23
  54:   80 93 62 00     sts 0x0062, r24
  58:   90 93 63 00     sts 0x0063, r25
  5c:   78 94           sei
  5e:   80 e0           ldi r24, 0x00   ; 0
  60:   90 e0           ldi r25, 0x00   ; 0
  62:   08 95           ret

每个操作都在&#39; cli&#39;之间执行。和&#39; sei&#39;这里,这意味着C类比预期更早地实例化。我希望首先执行添加,并且只在&#39; cli&#39;之间进行分配。和&#39; sei&#39;不知何故,整个表达式被优化为运算符&lt;&lt;()函数。

我尝试创建临时变量和其他技巧,但无法获得预期的行为。不幸的是我不太了解C ++标准, 所以我无法确定它是否是编译器错误或标准允许这样的执行顺序更改。至少我不明白平台之间的区别。

请帮助我如何在AVR平台中获得预期的执行顺序!

我希望这样的事情:

0000002a <main>:
  2a:   20 91 68 00     lds r18, 0x0068
  2e:   30 91 69 00     lds r19, 0x0069
  32:   40 91 6a 00     lds r20, 0x006A
  36:   50 91 6b 00     lds r21, 0x006B
  3a:   60 91 64 00     lds r22, 0x0064
  3e:   70 91 65 00     lds r23, 0x0065
  42:   80 91 66 00     lds r24, 0x0066
  46:   90 91 67 00     lds r25, 0x0067
  4a:   2e d0           rcall   .+92        ; 0xa8 <__addsf3>
  4c:   f8 94           cli
  4e:   60 93 60 00     sts 0x0060, r22
  52:   70 93 61 00     sts 0x0061, r23
  56:   80 93 62 00     sts 0x0062, r24
  5a:   90 93 63 00     sts 0x0063, r25
  5e:   78 94           sei
  60:   80 e0           ldi r24, 0x00   ; 0
  62:   90 e0           ldi r25, 0x00   ; 0
  64:   08 95           ret

我尝试了g ++版本4.9.2和5.3.0,结果相同。

提前完成,

Gyorgy Kovesdi

增加第一条评论: 全球对象&#39;顺序并不重要,只有类C,它是一个函数的本地,而且它的构造函数只针对这个例子中的f1 + f2之类的操作。 asm指令也不相关,构造函数可以有任何内容,这只是一个例子。

0 个答案:

没有答案