MDK C++中对内联的极度优化

先来看看我们SmartIRQ的具体实现

// 智能IRQ,初始化时备份,销毁时还原
class SmartIRQ
{
public:
    force_inline SmartIRQ(bool enable = false)
    {
        _state = __get_PRIMASK();
        if(enable)
            __enable_irq();
        else
            __disable_irq();
    }

    force_inline ~SmartIRQ()
    {
        __set_PRIMASK(_state);
    }
    
private:
    uint _state;
};

在构造的时候备份,然后根据参数决定打开还是关闭中断。 在系统内核时钟里面,关键操作需要关闭中断,最后打开,以免其它中断影响关键操作的原子事务性。 于是我们有:

ulong Time::CurrentTicks()
{
    SmartIRQ irq;

    uint value = (SysTick->LOAD - SysTick->VAL);
    if(SysTick->CTRL & SysTick_CTRL_COUNTFLAG)
    {
        Ticks += SysTick->LOAD;
    }

    return Ticks + value;
}

其中irq在离开作用域时被释放,自动调用SmartIRQ的析构函数,还原了中断状态 因为调用极其频繁,最高可能1us调用一次该函数,于是我们给SmartIRQ的构造和析构都加了force_inline强制使用内联。 总所周知,C++的内联其实就是以空间换时间,把一个函数的代码全部搬出来直接使用,省去了调用、压栈、弹栈、返回等操作。 SmartIRQ的析构函数就罢了,但是构造函数代码量还是有好几行的。 怀着试一试的心态调试该函数,直接观察汇编代码:

0x08000804 B570      PUSH     {r4-r6,lr}
0x08000806 F3EF8210  MRS      r2,PRIMASK
0x0800080A B672      CPSID    I
0x0800080C 4D0B      LDR      r5,[pc,#44]  ; @0x0800083C
0x0800080E 6969      LDR      r1,[r5,#0x14]
0x08000810 69AB      LDR      r3,[r5,#0x18]
0x08000812 1ACC      SUBS     r4,r1,r3
0x08000814 6929      LDR      r1,[r5,#0x10]
0x08000816 2300      MOVS     r3,#0x00
0x08000818 03C9      LSLS     r1,r1,#15
0x0800081A 2900      CMP      r1,#0x00
0x0800081C DA06      BGE      0x0800082C
0x0800081E 6886      LDR      r6,[r0,#0x08]
0x08000820 68C1      LDR      r1,[r0,#0x0C]
0x08000822 696D      LDR      r5,[r5,#0x14]
0x08000824 1975      ADDS     r5,r6,r5
0x08000826 4159      ADCS     r1,r1,r3
0x08000828 6085      STR      r5,[r0,#0x08]
0x0800082A 60C1      STR      r1,[r0,#0x0C]
0x0800082C 6885      LDR      r5,[r0,#0x08]
0x0800082E 68C1      LDR      r1,[r0,#0x0C]
0x08000830 1928      ADDS     r0,r5,r4
0x08000832 4159      ADCS     r1,r1,r3
0x08000834 F3828810  MSR      PRIMASK,r2
0x08000838 BD70      POP      {r4-r6,pc}

MDK C++编译器优化到了极度变态的地步! 不仅仅内联了,SmartIRQ里面有两个分支语句,直接被他省略了其中一个,因为参数true已经确定。 更加变态的是,本来采用SmartIRQ内部私有成员_state保存状态,析构时恢复的,它直接把这个状态保存到寄存器r2里面去,连_state的内存都给省了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python爬虫与算法进阶

学点算法之队列的学习及应用

约瑟夫问题 约瑟夫问题 有 n 个囚犯站成一个圆圈,准备处决。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过 k-1个...

38770
来自专栏数据结构与算法

洛谷P3381 【模板】最小费用最大流(dijstra费用流)

题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。 输入输出格式 输入格式: 第...

31260
来自专栏Java3y

【Java】几道让你拿offer的面试题

之前在刷博客的时候,发现一些写得比较好的博客都会默默收藏起来。最近在查阅补漏,有的知识点比较重要的,但是在之前的博客中还没有写到,于是趁着闲整理一下。

55700
来自专栏我是业余自学C/C++的

redis_3.0.7_sds.c_sdsull2str()

18740
来自专栏乐百川的学习频道

设计模式(二十四) 访问者模式

访问者模式提供了一种方法,将算法和数据结构分离。假设我们需要对一个数据结构进行不同的操作,就可以考虑使用访问者模式。访问者模式的要点在于,需要一个访问者接口,提...

24560
来自专栏安恒网络空间安全讲武堂

记一次JS木马分析

记一次JS木马分析 0x00 前言 随着 javascript 这类脚本语言的快速发展,它能展现的内容越来越多样,所运用的功能变得越来越强大。当运用在 web ...

60080
来自专栏黑泽君的专栏

java多线程、集合和IO面试题_02

16410
来自专栏程序员互动联盟

[WebKit] JavaScriptCore解析--基础篇(一)字节码的生成及抽象语法树的构建详情分析

看到HorkeyChen写的文章《[WebKit] JavaScriptCore解析--基础篇(三)从脚本代码到JIT编译的代码实现》,写的很好,深...

540100
来自专栏企鹅号快讯

Bruce.Wang-记一次对JS木马分析

0×00 前言 随着 javascript 这类脚本语言的快速发展,它能展现的内容越来越多样,所运用的功能变得越来越强大。当运用在 web 开发上时,增加了更多...

27860
来自专栏从流域到海域

《笨办法学Python》 第1课手记

《笨办法学Python》第1课手记 在powershell中打开Python输入如下代码: print "Hello World!" print "Hello...

24770

扫码关注云+社区

领取腾讯云代金券