凡亿专栏 | 嵌入式开发还有必要学汇编吗?
嵌入式开发还有必要学汇编吗?
最近又看到关于【嵌入式开发有没有必要学汇编的话题。


我觉得学汇编有学汇编的道理,不学也有不学的道理,这个很正常。不同的人有不同的观点,讨论激烈也很正常。


现在可能很少看到汇编程序了,但单片机的启动文件、RTOS底层等一些地方,依然还有汇编代码的身影。


不知道大家有没有学过汇编,或者有没有用汇编语言编过程?


下面结合我学习汇编的经历,以及汇编点灯给大家说说。

学习汇编语言


我在2010年学习单片机编程的时候,老师教学都还是用汇编教我们,包括教学实验,也是要求我们用汇编写程序。


MOV  A,#00HMOV  P1,A


我记得那会儿,老师要求我们把汇编指令背下来。虽然现在很多汇编指令写不出来了,但看到很多汇编代码,还是基本明白它的意思。


以前计算机三级(PC技术)的上机考试,就是用汇编编程,我那个时候上机考试还是满分。当时觉得自己很牛逼,现在看来就是一菜鸟


汇编转C语言


刚开始学习汇编那会儿,我真的用汇编在51单片机上写流水灯程序。后面看了用C语言写流水灯程序,突然发现,哇,用C语言写程序还能这么简单、方便。


于是,我就那个时候开始放弃了汇编,转向了C语言。包括后面我在大学实验室自己学习、DIY做东西、以及后面的全国大学生电子设计竞赛,都是用C语言编写的程序。


10行汇编程序,可能只需要一行C语言代码就能实现,这是C语言相比汇编简化的优点。

但是,C语言编写的程序,经过编译,也会转为汇编。比如我们在线调试代码的时候,会看到类似的“汇编窗口”:


image.png


因为以前单片机的运行速度不高,且内存和Flash容量不大,要求节约程序空间。


所以使用汇编的优点:代码运行效率更高、更节约代码存储空间

对比汇编和C语言点灯程序


汇编语言写程序的主要缺点:语法复杂、可读性差等。


下面分享一个实例:51单片机上的流水灯程序。分别用C语言和编写出来,大家对比一下就知道了。


C语言版:



/******************** 宏定义 **************************/#define   MAIN_Fosc    22118400L  //定义主时钟


/******************** 延时函数 **************************/void  delay_ms(u8 ms){     u16 i;   do{        i = MAIN_Fosc / 13000;      while(--i)  ;   //14T per loop     }while(--ms);}


/******************** 主函数 **************************/void main(void){  P0M1 = 0;  P0M0 = 0;  //设置为准双向口  P1M1 = 0;  P1M0 = 0;  //设置为准双向口  P2M1 = 0;  P2M0 = 0;  //设置为准双向口  P3M1 = 0;  P3M0 = 0;  //设置为准双向口  P4M1 = 0;  P4M0 = 0;  //设置为准双向口  P5M1 = 0;  P5M0 = 0;  //设置为准双向口  P6M1 = 0;  P6M0 = 0;  //设置为准双向口  P7M1 = 0;  P7M0 = 0;  //设置为准双向口


 while(1)  {    P17 = 0;    delay_ms(250);    delay_ms(250);    P17 = 1;    P16 = 0;    delay_ms(250);    delay_ms(250);    P16 = 1;    P47 = 0;    delay_ms(250);    delay_ms(250);    P47 = 1;    P46 = 0;    delay_ms(250);    delay_ms(250);    P46 = 1;  }}

汇编语言版:



;******************** 宏定义 **************************/Fosc_KHZ  EQU  22118  ;22118KHZ


STACK_POIRTER  EQU    0D0H  ;堆栈开始地质



;******************** 延时函数 **************************/F_delay_ms:  PUSH  02H    ;入栈R2  PUSH  03H    ;入栈R3  PUSH  04H    ;入栈R4


 MOV    R2,A


L_delay_ms_1:  MOV    R3, #HIGH (Fosc_KHZ / 13)  MOV    R4, #LOW (Fosc_KHZ / 13)L_delay_ms_2:  MOV    A, R4      ;1T    Total 13T/loop  DEC    R4        ;2T  JNZ    L_delay_ms_3  ;4T  DEC    R3L_delay_ms_3:  DEC    A        ;1T  ORL    A, R3      ;1T  JNZ    L_delay_ms_2  ;4T  DJNZ  R2, L_delay_ms_1


 POP    04H    ;出栈R2  POP    03H    ;出栈R3  POP    02H    ;出栈R4  RET



;******************** 主程序 **************************/    ORG    0100H    ;resetF_Main:  CLR    A  MOV    P0M1, A   ;设置为准双向口   MOV    P0M0, A  MOV    P1M1, A   ;设置为准双向口   MOV    P1M0, A  MOV    P2M1, A   ;设置为准双向口   MOV    P2M0, A  MOV    P3M1, A   ;设置为准双向口   MOV    P3M0, A  MOV    P4M1, A   ;设置为准双向口   MOV    P4M0, A  MOV    P5M1, A   ;设置为准双向口   MOV    P5M0, A  MOV    P6M1, A   ;设置为准双向口   MOV    P6M0, A  MOV    P7M1, A   ;设置为准双向口   MOV    P7M0, A


 MOV    SP, #STACK_POIRTER  MOV    PSW, #0    ;选择第0组R0~R7


L_MainLoop:  CLR    P1.7  MOV    A, #250  LCALL  F_delay_ms    ;延时250ms  LCALL  F_delay_ms    ;延时250ms  SETB  P1.7


 CLR    P1.6  MOV    A, #250  LCALL  F_delay_ms    ;延时250ms  LCALL  F_delay_ms    ;延时250ms  SETB  P1.6


 CLR    P4.7  MOV    A, #250  LCALL  F_delay_ms    ;延时250ms  LCALL  F_delay_ms    ;延时250ms  SETB  P4.7


 CLR    P4.6  MOV    A, #250  LCALL  F_delay_ms    ;延时250ms  LCALL  F_delay_ms    ;延时250ms  SETB  P4.6


 SJMP  L_MainLoop
上面两个程序,实现的功能都一样(流水灯),但对比代码,大家发现有啥区别?


对于有汇编基础的同学来说,可能这个简单的流水灯程序还是很好理解。


但是,对于大部分人来说,肯定都会觉得汇编很难读。是的,这个是汇编的“特点”。


最后


汇编语法,对于绝大部分读者来说,我现在是不建议再深入学习了,只需要了解一些基础的内容即可。


有少部分人,想从事底层开发,比如底层驱动、单片机验证、固件库开发等这些读者,有时间还是可以进一步了解汇编的一些技术。

声明:本文转载自嵌入式专栏 公众号,如涉及作品内容、版权和其它问题,请于联系工作人员,我们将在第一时间和您对接删除处理!

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表凡亿课堂立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。
相关阅读
进入分区查看更多精彩内容>
精彩评论

暂无评论