经验谈:68HC908单片机汇编程序中变量的使用
时间:11-05 16:34 阅读:853次
*温馨提示:点击图片可以放大观看高清大图
简介:这篇文章是谈谈68HC908单片机汇编程序中变量的使用,一般点偏激的RAM资源有两种用途。
68HC908单片机汇编程序中变量的使用 单片机的RAM资源一般有两个用途,一是保存变量,另外就是作为系统堆栈使用。编程时变量的使用是一个应当注意的问题。 我们使用的变量一般可以分为两类:全局变量、局部变量。全局变量对所有的子程序都是可见的,在程序运行的任何时刻都可以访问得到;局部变量只对当前的子程序有效,其它程序不会访问。全局变量可用于在子程序之间传递信息,也可以用于保存系统运行中要用到的必要信息。可以像下面一样定义一个单字节全局变量。 org (ram开始地址) variablermb 1 下面是一个使用全局变量传递标志的例子。程序中flag为已定义的全局变量。在sub1中,程序检测flag中的flag1位,如果为高则等待,否则运行下一条指令。sub2为一中断服务程序,在满足一定的条件下,清除flag的flag1位,使得sub1可以响应,并运行其下面的指令。 sub1: ... brset flag1,flag,* ;检测flag中的flag1位,如果为高 ;则等待 sub2 ... bclr flag1,flag ;清除flag中的flag1位 下面有个关于局部变量的例子,sub1中使用var1作为循环计数器,sub2中也使用了var1。如果sub1在运行过程中被sub2中断,sub2将var1的值改变,中断返回以后sub1将产生不可预料的结果,严重时可能会使sub1陷入死循环中。在这种情况下,sub1不能使用全局变量var1作循环计数器。 sub1: mov #10,var1 ;do something dec var1 beq quit ;结果为0则跳出循环 bra dosth ;否则循环继续 sub2: ;do something mov #10,var1 ;改变var1的值会影响sub1正常运行 要解决这个问题就需要使用局部变量。有两种办法:一是使用68HC908的内部寄存器,如累加器或索引寄存器。当子程序被中断时,所有的寄存器(H寄存器除外)都会被压入堆栈保存,中断返回时寄存器被恢复为中断前的值。若使用x寄存器,上述程序可更改如下: sub1: ldx #10 ;do something decx beq quit ;结果为0则跳出循环 bra dosth ;否则循环继续 sub2: ;do something ldx #10 ;改变x的值不影响sub1 这种方法的优点是直观,缺点是如果在子程序中内部寄存器还要作其它用途,那么在作其它用途之前需要保存寄存器的值(如将寄存器压栈),或是程序中需要使用多个循环计数,这时候内部寄存器就不够用了。 另一种方法是使用系统堆栈。我们知道进行一次压栈操作将使堆栈指针sp减1。如果人为地将sp减1,就可以从系统堆栈中获得一个字节的空间,使用这种办法将sub1改写如下: sub1: ais #-1;sp-1得到一个字节的空间,地址为sp+1 ;do something dec 1,sp ;对地址sp+1中的数据进行操作 beq quit ;结果为0则跳出循环 bra dosth ;否则循环继续 ... ais #1 ;恢复sp !!!切记 如果sub1在运行过程中被中断,中断响应过程中有一系列的压栈操作,每次压栈都在原来的基础之上将sp-1;而我们在sub1中定义的局部变量的内容却不会被改变,而且其它程序中的任何合法操作都不会改变sub1中局部变量的值。当中断返回时,sp又被恢复成sub1中原来的数值,这样又可以正常使用这个局部变量了。如果需要n个局部变量,只要将sp减n即可。使用堆栈作局部变量,在子程序返回之前一定要恢复sp原来的值,否则程序返回不到正确的地址。 总之,如果需要在子程序之间传递信息,可以使用全局变量,而只要是仅在子程序中有效的变量、标志都应该考虑使用局部变量。