ASM真要被扫进历史的垃圾堆了吗?

简介: ASM真要被扫进历史的垃圾堆了吗?

最近浏览一个挺流行的视频 – X天学会单片机。内容确实通俗易懂,制作的比较用心。但其中的有个观点笔者不敢苟同,就是现在 C 语言已经强大到胜任所有任务,大家没有必要再去学习汇编语言了,直接从 C 学起就行了。这种观点似乎有一定道理,我甚至怀疑现在是不是真的有很多同学不再学习汇编了。特别是现在大多数厂商都提供了完备的驱动代码的情况下,我们做项目基本上用不到写 ASM 代码了。ASM 就要被时代淘汰了!可真的是这样吗?

下面我们结合两个实际工程中碰到的例子谈一下,掌握 ASM 语言对我们写出稳定高效代码的必要性。看第一个例子,为说明问题,代码我们做了简化:



我们看代码,主程序翻转 PORTA 的引脚 0,定时中断服务程序翻转 PORTA 的引脚 1。乍一看很难看出有什么问题。有不少同学就是这么中招儿的。这要是控制一些 LED 指示灯或蜂鸣器之类的还好,最多就是偶尔看着有点乱,或出点儿噪音。要是控制设备没准儿就要出大问题了。有什么问题呢?因为中断发生时,主程序将在上一条正在执行中的语句执行完后中止运行。这里一定要注意,这里说的语句,不是一条 C 语句,而是一条 ASM 语句。我们在调试环境看一下反汇编。一条 C 语句被编译成了多条 ASM 语句。






LDRH r1, [r5,#0x14]        
EORS r1,r1,r4                    
STRH r1,[r5,#0x14] 

我们看到一条 C 语句实际上编译为 3 句 ASM,(1)把 PORTA 当前内容读进 r1,(2)最低位通过异或取反,(3)把取反后的值输出至 PORTA。如果中断恰好发生在 (1)或 (2)的执行期间,那么中断服务程序对 PORTA 引脚 1 的操作,会被主程序中语句(3)覆盖掉。

要避免这种情况,可以在操作 IO 端口(或其它类似的操作)前禁止中断,操作完之后再允许中断。在一些有位带(Bit Map)的单片机里,对单个引脚的操作可以通过位带区操作,避免各引脚之间互相影响。

汇编语言的使用,还可以大幅度的提高代码的效率。即使现在编译器的效率已经挺高了,但毕竟机器还是要比人笨一点儿。举个栗子,有不少工程里面需要用到浮点运算。如果直接调用浮点运算库,可以轻松的完成任务。但这样有一个限制,就是运算过程一直以最大的精度来运算,相当浪费 MCU 的时间。我们的应用可能并不需要这么高的精度,而是需要尽快的完成运算并保留一定精度即可。在此情况下,如果我们用嵌入 ASM 做运算,可以通过减少迭代运算次数 (精度和迭代运算次数成正比)达到快速完成运算。在发动机控制等分秒必争的领域,有时候这样做是很有必要的。

相关文章
|
缓存 Prometheus Kubernetes
服务网格ASM使用FAQ之(2):使用ASM实现服务慢启动模式以支持预热功能
### 背景 在未启用慢启动预热能力时, 每当新目标Pod加入时,请求方都会向该Pod发送一定比例的流量, 不支持新 Pod 的渐进式流量增加。这对于需要一些预热时间来提供全部负载的服务可能是不可取的,并且可能会导致请求超时、数据丢失和用户体验恶化。 作为一个实际示例,上述问题体现在基于 JVM 的 Web 应用程序中,这些应用程序使用水平 pod 自动缩放。当服务刚启动时,它会被大量请求淹没
328 0
|
Oracle 关系型数据库 网络架构
asm 状态INTERMEDIATE
asm INTERMEDIATE,asm 磁盘中状态显示INTERMEDIATE。
3188 0
|
Oracle 关系型数据库 数据库
从文件系统迁移到ASM上
从文件系统迁移到ASM上
1408 0
|
存储 Oracle 关系型数据库
|
SQL Web App开发 数据库
|
SQL 测试技术 数据库
|
存储 Oracle 关系型数据库
|
Oracle 关系型数据库 数据库
|
SQL Oracle 关系型数据库
|
SQL Oracle 关系型数据库