avr-gcc破坏性优化

  发布于 2023-02-13 10:30

我正在使用avr-gcc 4.8.2编程Atmel ATtiny13a微控制器.

这是我的c代码:

#include  
#include  

int main(void) {
    DDRB = 1; // PB0 is output
    for (uint8_t i = 0; i < 10; i++) {
        PORTB = 1;
        _delay_ms(500);
        PORTB = 0;
        _delay_ms(500);
    }
    while(1);
}

void test(void) {
    DDRB = 1; // PB0 is output
    for (uint8_t i = 0; i < 10; i++) {
        PORTB = 1;
        _delay_ms(100);
        PORTB = 0;
        _delay_ms(100);
    }
}

从不通过主功能调用测试功能(LED快速闪烁),因此控制器只应进入主功能(慢速闪烁).

当我编译代码时-O1,一切正常:

avr-gcc -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -mmcu=attiny13 -DF_CPU=1200000   -Wall -Wstrict-prototypes -Os -c test.c -o test.o
avr-gcc  test.o -o test.elf
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature test.elf test.hex

但是如果我使用-Os(优化尺寸)或者-O2,微控制器运行test功能而不是main功能:LED快速闪烁并且永不停止.

-Os标志是否太危险而无法使用,是否应该避免?或者我的代码中是否可以更改某些内容以避免此类错误?ATtiny13a只有1K的闪光灯,因此尺寸减小很重要.


编辑:正如评论中所建议的,这里是汇编器差异-O1-O2:http://www.diffchecker.com/3l9cdln6

在那里,您可以看到-O2将第一部分更改.text.text.startup.

--- test.o1.txt 2013-12-03 19:10:43.874598682 +0100
+++ test.o2.txt 2013-12-03 19:10:50.574674155 +0100
@@ -3,7 +3,7 @@
 __SREG__ = 0x3f
 __tmp_reg__ = 0
 __zero_reg__ = 1
-       .text
+       .section        .text.startup,"ax",@progbits
 .global        main
        .type   main, @function
 main:

这可能是这里的主要问题.经过一些进一步的测试后,我发现罪魁祸首就是-freorder-functions优化.有没有办法防止这种行为?

1 个回答
  • 我做了一些进一步的调试,发现"罪魁祸首"是-freorder-functions优化.它在联机帮助页中记录如下:

    -freorder-functions
        Reorder functions in the object file in order to improve code locality.
        This is implemented by using special subsections ".text.hot" for most
        frequently executed functions and ".text.unlikely" for unlikely executed
        functions. Reordering is done by the linker so object file format must
        support named sections and linker must place them in a reasonable way.
    

    文档中的最后一行解释了我遇到的问题.如果我们再次查看原始问题的编译命令:

    $ avr-gcc -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct \
       -fshort-enums -mmcu=attiny13 -DF_CPU=1200000   -Wall -Wstrict-prototypes \
       -Os -c test.c -o test.o
    $ avr-gcc  test.o -o test.elf
    

    ...我们看到我将优化标志传递给编译器,但没有传递给链接器.我假设CFLAGS唯一影响编译而不是链接,所以我没有将它们传递给链接器,但在那种情况下我错了.

    结果:汇编代码由编译器重新排序(包括适当的标签),但链接器不考虑这些标签.并且因为函数由编译器test放在函数之前main而不是由链接器重新排列,这就是在微控制器上实际执行的代码.

    所以解决方案结果是:编译器标志也应该传递给链接器!

    2023-02-13 10:33 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有