历史上的今天
返回首页

历史上的今天

今天是:2024年10月11日(星期五)

正在发生

2021年10月11日 | STM8与汇编语言(1)(2)(3)

2021-10-11 来源:eefocus

STM8与汇编语言(1)


不知是心血来潮,还是其它因素,突然又想起玩汇编语言了。这几年也没少跟单片机打交道,包括51系列,430系列,ARM系列,但都是用C语言来开发。不过由于使用C语言,实际上对这些CPU的了解还是不够深刻,当然除了51之外,因为那是我多年前曾经用汇编开发过的芯片。尽管当今C语言已经在嵌入式产品的开发过程中成为主流,但我个人依然认为,要想真正了解CPU的特点,还得用汇编语言。不知道这种观点是对还是错,也许是因为自己从硬件做起,写过机器码,用汇编语言做过优化,因此对汇编语音有一种特殊的偏爱。


51系列的芯片用多了,感觉有时写起程序来不太方便,因此总想寻找一些其它的8位单片机玩玩,正好手头有一个ST的三合一开发板,那是09年参加ST研讨会上买的,一直躺在那里,与其躺在那里,不如拿出来玩玩。


这几年,ST在国内推广STM32,力度不小,不过我一直没有用过,只是初步地看看资料。原因在于在32位单片机方面,我一直在用Luminary公司的LM3S1138,感觉不错,一直都很顺利。09年ST举办的研讨会上,ST除了介绍STM32外,也介绍了STM8,当时听了以后,觉得还行。尤其是会上的低功耗演示给我留下了很深刻的印象。


基于这些,我决定好好地玩一下STM8芯片,并将玩的结果拿出来与大家共享。

 

STM8与汇编语言(2)


第一次打开STM8的手册时发现,CPU中的寄存器只有6个,即A、X、Y、SP、PC和CC。这几个寄存器,看上去特象早年苹果机使用的微处理器6502。在眼下都是多寄存器的RISC潮流下,不知ST推出的这种CPU架构有什么意图?这样的芯片能否与Microchip或者Atmel的RISC结构的MCU竞争呢?在此我无意做评论,我只想了解这颗芯片。


通过仔细研究,我发现由于STM8采用了32位宽度的程序存储器结构,使得大部分的指令都能在一个周期内取出,并且采用了哈佛结构和流水线,相当多的指令也都是单周期完成的。这样的话,虽然CPU是CISC架构的,但也基本上达到了单周期指令的效果,就像手册上说的,CPU的性能达到了20MISP◎24MHZ。就这一点来说,我个人感觉STM8还真不错。


举个例子来说,如果我们要完成内存中的2个8位无符号数相加,结果还保存到内存中,用C语言描述成:

unsigned char a,b,c;

c = a + b;

这一段程序,用STM8汇编可以写成如下代码:

LD    A, $1000     

ADD  A, $1001      

LD    $1002, A

这里假设a,b,c这3个变量分别存储在内存中,地址为1000,1001和1002。从STM8的手册上可以查到,这3条指令都是单周期的,完成一个加法,只需要3个时钟周期,可见STM8的CPU执行速度还是相当快的。


在这种传统的所谓CISC架构中,我特别关心累加器A与内存的访问速度,因为如果累加器与内存的访问速度是单周期的话,实际上我们就可以将内存当寄存器来看,这样写程序时就相当于拥有了一个大的寄存器阵列,或者说我们也就没必要再去考虑变量在内存中还是在寄存器中。也正是因为这一点,我对STM8越来越感兴趣了。


STM8与汇编语言(3)


STM8的开发环境用起来还是不错的,可以到ST的网站上下载安装程序ST_Toolset.exe。利用该环境可以开发用汇编语言写的程序,而且与ST的三合一开发板配合起来,确实非常方便。


不过如果要想用C语言来开发,稍微有点麻烦,得去别的公司下载C的编译器(CXSTM8_16K.exe),而且下载完以后,还得去注册,等待许可文件。实际上,我也按照ST介绍的方法做了,但始终都没有收到许可文件,也许本人实在愚笨。但不管怎么说,我觉得ST这一点做得相当不好,实在有点抠门。既然是免费的,为什么不一起打包提供给客户,这么麻烦,多耽误客户使用,得少卖多少STM8的芯片。


言归正传,还回到正题。用汇编语言开发程序,最简单的就是利用ST开发环境中提供的汇编程序框架自动生成功能。打开开发环境后,在File菜单中选择New Workspace,点击Create workspace and project图标,然后就可以建立项目,在工具链中选ST Assembler Linker,最后选择MCU的型号,点击OK,就完成了一个项目的建立。这个环境与微软的VC6开发环境很象,点开项目文件中的Source Files,能看到系统自动生成好了一个汇编语言的框架,我们编写程序只要在这框架基础上就可以了。其实不用编写任何一条指令,这个框架程序是能够编译通过,并下载运行的。


自动生成的项目中包含3个重要的文件:mapping.inc,mapping.asm和main.asm。

mapping.inc文件中定义的是一些常量,mapping.asm文件中定义的是一些内存的分配,主要的汇编代码都在main.asm。


下面是main.asm中的汇编代码及注释。


stm8/



     #include "mapping.inc"



      segment 'rom'

; 下面是定义一个标号,ST汇编的写法,有点不习惯

; 这里的main标号是复位后的第一条指令,与后面的中断向量表中

; 的名字是对应的

main.l   

      ; initialize SP

      ldw X,#stack_end

      ldw SP,X                          ; 设置堆栈指针



      #ifdef RAM0     

; 如果定义了RAM0,则要汇编以下代码

      ; clear RAM0

ram0_start.b EQU $ram0_segment_start

ram0_end.b EQU $ram0_segment_end

      ldw X,#ram0_start   ;寄存器X指向要清除的内存起始地址   

clear_ram0.l          ;这是一个标号定义,用于后面的跳转指令

      clr (X)            ;对应的内存单元清0

      incw X            ;寄存器X+1,指向下一个单元 

      cpw X,#ram0_end       ;比较寄存器X是否等于内存的最后一个地址

      jrule clear_ram0      ;若不等于,则循环

     #endif



      #ifdef RAM1

; 如果定义了RAM1,则要汇编以下代码,代码含义与上面完全一样

      ; clear RAM1

ram1_start.w EQU $ram1_segment_start

ram1_end.w EQU $ram1_segment_end

      ldw X,#ram1_start

clear_ram1.l

      clr (X)

      incw X

      cpw X,#ram1_end    

      jrule clear_ram1

     #endif



      ; clear stack

; 将堆栈区的内存单元清0,代码含义与上面完全一样

stack_start.w EQU $stack_segment_start

stack_end.w EQU $stack_segment_end

      ldw X,#stack_start

clear_stack.l

      clr (X)

      incw X

      cpw X,#stack_end    

      jrule clear_stack



infinite_loop.l                     ; 定义一个标号

;由于是一个框架,初始化内存后,进入一个死循环

      jra infinite_loop                



;下面代码写的是一段中断服务程序,不过也是空的

     interrupt NonHandledInterrupt

NonHandledInterrupt.l

; 当进入中断服务程序后,无其它动作,直接返回

  iret                            


; 下面这张表很重要,定义了STM8所有的硬件中断对应的中断

; 服务程序的入口地址

  segment 'vectit'

      dc.l {$82000000+main}                          ; reset

      dc.l {$82000000+NonHandledInterrupt}    ; trap

      dc.l {$82000000+NonHandledInterrupt}    ; irq0

      dc.l {$82000000+NonHandledInterrupt}    ; irq1

      dc.l {$82000000+NonHandledInterrupt}    ; irq2

      dc.l {$82000000+NonHandledInterrupt}    ; irq3

      dc.l {$82000000+NonHandledInterrupt}    ; irq4

      dc.l {$82000000+NonHandledInterrupt}    ; irq5

      dc.l {$82000000+NonHandledInterrupt}    ; irq6

      dc.l {$82000000+NonHandledInterrupt}    ; irq7

      dc.l {$82000000+NonHandledInterrupt}    ; irq8

      dc.l {$82000000+NonHandledInterrupt}    ; irq9

      dc.l {$82000000+NonHandledInterrupt}    ; irq10

      dc.l {$82000000+NonHandledInterrupt}    ; irq11

      dc.l {$82000000+NonHandledInterrupt}    ; irq12

      dc.l {$82000000+NonHandledInterrupt}    ; irq13

      dc.l {$82000000+NonHandledInterrupt}    ; irq14

      dc.l {$82000000+NonHandledInterrupt}    ; irq15

      dc.l {$82000000+NonHandledInterrupt}    ; irq16

      dc.l {$82000000+NonHandledInterrupt}    ; irq17

      dc.l {$82000000+NonHandledInterrupt}    ; irq18

      dc.l {$82000000+NonHandledInterrupt}    ; irq19

      dc.l {$82000000+NonHandledInterrupt}    ; irq20

      dc.l {$82000000+NonHandledInterrupt}    ; irq21

      dc.l {$82000000+NonHandledInterrupt}    ; irq22

      dc.l {$82000000+NonHandledInterrupt}    ; irq23

      dc.l {$82000000+NonHandledInterrupt}    ; irq24

      dc.l {$82000000+NonHandledInterrupt}    ; irq25

      dc.l {$82000000+NonHandledInterrupt}    ; irq26

      dc.l {$82000000+NonHandledInterrupt}    ; irq27

      dc.l {$82000000+NonHandledInterrupt}    ; irq28

      dc.l {$82000000+NonHandledInterrupt}    ; irq29


      end


把这个项目Build后,点击Debug中的Start Debugging就可以将程序下载到ST的三合一板上了,然后点击Run,程序就运行起来了,不过由于框架程序是一个空程序,初始化内存后就进入死循环了,因此什么效果也看不见。因此我们必须在框架程序的基础上,编写自己的程序。后面的程序例子都是在这个框架程序的基础上编写的。


推荐阅读

史海拾趣

法思特(FAST)公司的发展小趣事
随着使用环境和需求的变化,可能需要对控制电路进行调整和优化,以适应新的使用条件。
BELLING LEE公司的发展小趣事

在电子行业的初期,BELLING LEE公司以其对新技术的敏锐洞察力和强大的研发能力脱颖而出。公司投入大量资源研发出了一款具有革命性的高效能电子芯片,这一创新产品不仅提高了电子设备的性能,还大大降低了能耗。凭借这一技术突破,BELLING LEE公司迅速在电子市场上获得了认可,并逐渐建立起自己的市场地位。

HTSEMI( Jin Yu Semiconductor )公司的发展小趣事

为了进一步提升技术实力,金宇半导体积极与国内外知名高校和科研机构建立合作关系。2010年,公司与某顶尖大学联合成立了“先进半导体技术研究中心”,共同开展前沿技术的研发。通过产学研的紧密合作,金宇半导体在先进制程工艺、芯片封装测试等领域取得了重大突破,成功推出了多款具有自主知识产权的高端芯片产品,进一步巩固了其在行业内的领先地位。

FOSLINK公司的发展小趣事

面对全球气候变化的严峻挑战,FOSLINK公司积极响应国家关于绿色发展的号召,将绿色转型作为企业发展的重要方向。公司致力于研发和生产低能耗、环保型的电子产品,并不断优化生产工艺流程,减少资源消耗和环境污染。同时,FOSLINK还积极推广绿色供应链管理,与供应商和客户共同构建绿色、低碳的产业链生态。这一系列的绿色转型举措,不仅彰显了FOSLINK的社会责任感,也为其赢得了更多消费者的青睐和支持。

BROTHER公司的发展小趣事

BROTHER公司的历史可以追溯到1908年,当时安井兼吉在名古屋市开设了工业缝纫机维修及零部件生产的“安井缝纫机商会”。随着时间的推移,公司逐渐发展成为缝纫机领域的领导者。然而,BROTHER并没有满足于在缝纫机领域的成功,而是开始寻求跨界发展的机会。上世纪中叶,随着电子技术的兴起,BROTHER开始利用其在机械制造和精密加工方面的技术优势,涉足电子产品领域。通过不断研发和创新,BROTHER成功推出了一系列电子产品,逐渐在电子行业崭露头角。

DCCOM [ DC COMPONENTS ]公司的发展小趣事

随着公司规模的扩大和市场份额的提升,DCCOM开始注重品牌建设和市场推广。公司投入大量资金进行品牌宣传和市场推广,通过参加各种行业展会、举办技术研讨会等方式提高品牌知名度和影响力。这些举措使得DCCOM的品牌价值得到了显著提升。

问答坊 | AI 解惑

怎么用VHDL语言实现1602的字母的直接输入

我想通过FPGA实现与1602的控制 想显示几个英文字母 但是不知道用VHDL语言怎么实现 知道的告诉一声…

查看全部问答>

计数器与定时器

计数器与定时器一、计数概念的引入 从选票的统计谈起:画“正”。这就是计数,生活中计数的例子处处可见。例:录音机上的计数器、家里面用的电度表、汽车上的里程表等等,再举一个工业生产中的例子,线缆行业在电线生产出来之后要计米,也就是测 ...…

查看全部问答>

能否在Hook NtCreateProcessEx时得到命令行参数

能否在Hook NtCreateProcessEx时得到命令行参数 谢谢…

查看全部问答>

几款大公司的LED灯泡跟大家分享

几款大公司的LED灯泡跟大家分享  …

查看全部问答>

LM3S5956中断问题

我用的开发环境是keil4.20,同样的UART程序,在一个工程里可以运行,另一个工程里却不能运行,“属性设置”一样,库函数也一样。不能运行的那个工程中,在单步调试的时候,串口接收数据时,程序会停留在未知中断的位置。是怎么回事?请高人指点,谢 ...…

查看全部问答>

申请使用LX9

[ 本帖最后由 supereic 于 2011-8-17 15:00 编辑 ]…

查看全部问答>

求版主帮忙,复位成功,初始化收不到00.

初来咋到,前两天把帖子贴嵌入式了!   大致代码如下,用的是Znfat的代码,复位成功了,初始化不行。请大家帮忙看看。比较急 #include \"STC12C5A32S2.H\"#define DELAY_TIME 10#define TRY_TIME 200void SD_spi_write(unsigned char x) { ...…

查看全部问答>

怎么在不提高电源的情况下级联更多的三极管???

怎么在不提高电源的情况下级联更多的三极管???电源3v [ 本帖最后由 boofeng2002 于 2012-4-7 15:42 编辑 ]…

查看全部问答>

线性汇编数组问题

最近刚开始接触,有个问题想请教一下各位大大们我如何在线性汇编中调用C语言中已经定义的数组 例如:int A[3]={0,1,2};B[2][3]={{0,1,2},{0,1,2},{0,1,2}}如果在线性汇编中如何定义数组并赋值(一维、二维、三维),如何调用数组针对结构体如何写成 ...…

查看全部问答>

急求,msp430f449如何倍频到16M

通过设置SCFQCTL=121可以倍频工作在8M,但是好像最大也就是128,如果工作在16M呢?…

查看全部问答>