可能有一些人士认为汇编不重要,现在都有C语言编译器了,为什么还需要学习汇编?这个问题需要对不同的人去分来看,如果是学习上层应用软件的,汇编的确不那么重要,但是如果是底层驱动或者平台架构的,汇编会变得非常的重要。
下面举几个例子说明汇编的重要性:
1 系统的启动代码必须要汇编去编写,因为需要涉及到设置C语言运行栈指针,操作CPU内部协处理器等,C语言是无法完成的。
2 由于编译器优化的原因,往往会过度优化而导致C语言经过编译器后原有的逻辑性为和用户的逻辑行为不一致,这个时候只能通过反汇编去找出到底编译器的优化错误到底在哪里。最常见的情况就是变量不加volatile在某种情况下会被编译器优化掉,此时唯一的跟踪方法就是反汇编,才能走到根本原因。
3操作系统的移植必须要用汇编才能做到,因为涉及到cpu寄存器在栈的保存,还原等等操作,C语言是无法做到的。
4 在某种情况下,特别是一些运算的算法,编译器可能不会采用高效率的汇编语言去优化,这个时候用户觉得性能不够的话,
汇编的学习往往是嵌入式软件工程师成为系统平台架构师的必备标准。
有很多读者可能认为每一种cpu的汇编都不同,而且不同的编译器平台,诸如iar, keil, gcc 都不同,怎么去学习呢,似乎是一种不可能的任务。答案肯定是可以学会的,而且很简单。下面举例说明学习方法:
首先你要有armv7-m的手册,这个手册可以去arm官网去下载,前面有说明过在哪里下载,不再复述。手册里面有如下的内容需要粗略看一下,但是不需要记忆,只要会查就行:
<ignore_js_op>
然后可以下载官网的m3以及m4工程。打开后仿真运行到某一个C语言断点,然后看反汇编:
<ignore_js_op>
比如设置到断点到task_obj->suspend_count = 1u 这一句。可以看到对应的反汇编语句是STRB r10,[r4,#0x1B],然后我们看一下下图的寄存器值:
<ignore_js_op>
可以看到r10寄存器里面的值是1, r4寄存器里面的值是0x20002dec。查阅strb 的指令可以看到STRB r10,[r4,#0x1B]的意思是说把r10这个寄存器的值存到r4 + 0x1b 这个内存地址里面去,也就是说放到0x20002e07这个内存地址里面去。当我们单步执行这条指令后,可以利用观察内存的工具可以看到:
<ignore_js_op>
很清楚0x20002e07这个内存的位置里面的值是1, 验证了之前的汇编语句。
上面只是演示了一个很简单的例子,但是已经能够充分说明学习的方法,这个方法是笔者目前所能想到的最快学习汇编的方法,也就是说把C语言反汇编后的汇编语句拿出来直接使用就好了。其它的例子,读者可以举一反三,相信学习汇编以后并不会难倒各位。