学习笔记(四)——ARM汇编

  在CM3上一般使用C语言或者汇编语言编程,使用C语言开发大型程序,汇编语言则可以实现一些特殊功能,比如操作特殊功能寄存器、用c写效率不够高的程序等,因此学会ARM汇编语言是精通arm编程的前提。

  以一个HelloWorld程序作为例子来学习ARM汇编,注释部分详细介绍了程序是怎么运行的,很适合新手,当然,汇编语言的语法就当你已经学过了。

STACK_TOP     EQU     0x20002000             ;顶格写常量定义,这里是定义堆
UART0_BASE    EQU    0x4000C000              ;栈指针的地址、UART的一些常量
UART0_FLAG    EQU    UART0_BASE+0x018        ;定义
UART0_DATA    EQU    UART0_BASE+0x000  
    AREA | Header Code|, CODE         ;AERA定义一个名为HeaderCode的代码段
    DCD    STACK_TOP                  ;为栈分配一片连续的字存储单元
    DCD    Start
    ENTRY                             ;程序入口,一个汇编程序至少有一个ENTRY
Start                                 ;标号,顶格书写,这里是偏移地址的标记
    MOV    R0,    #0                  ;将0写入寄存器
    MOV    R1,    #0
    MOV    R2,    #0
    MOV    R3,    #0
    MOV    R4,    #0
    BL       Uart0Initialize          ;B简单跳转,BL带连接(保存在R14(LR)连接寄存器
                                      ;中)跳转,一般用于子程序,便于从子程序返回
    LDR    R0,    =HELL0_TXT          ;把字符串数据装载到寄存器,LDR字LDRH半字LDRB字节
    BL    Puts                        ;跳转至Puts子程序
deadend                               ;一个死循环里不停跳转
    B    deadend
;--------------------------------------------------------------------------------------
;各个子程序
;--------------------------------------------------------------------------------------
Puts                                  ;标号,代表子程序名称,该子程序作用是往UART送一个字符串,入口条件
                                      ;是当前R0=待输出字符串的起始地址,且以0结尾
    PUSH    {R0, R1, LR}              ;将R0,R1,LR入栈
    MOV    R1,    R0                   
PutLoop
    LDRB   R0, [R1], #1               ;取一个字节至R0,再自增1字节地址
    CBZ     R0, PutsLoopExit          ;若R0为0则跳转
    BL       Putc                     ;跳转至Putc子程序
    B        PutsLoop
PutLoopExit
    POP    {R0, R1, PC}               ;出栈
;--------------------------------------------------------------------------------------
Putc                                  ;子程序,作用是使用UART发一个字符串
    PUSH    {R1, R2, LR}
    LDR    R1,    =UART0_FLAG
PutcWaitLoop
    LDR    R2,    [R1]    
    TST    R2,    #0x20               ;TST是按位与并将结果更新CPSR标志位的值,这
                                      ;一句是与0x20按位与,检查“发送缓存满”标志
    BNE    PutWaitLoop                ;不为0则跳转,即已满则重试
    LDR    R1,    =UART0_DATA         ;有空位时将UART的寄存器地址加载到R1中
    STRB  R0,    [R1]                 ;将R0中的数据写入以R1数据为地址的寄存器中
    POP    {R1, R2, PC}
;--------------------------------------------------------------------------------------
Uart0Initialize                       ;UART初始化程序,与硬件有关,略
    BX     LR
;--------------------------------------------------------------------------------------
HELLO_TXT                             ;定义一个以0结尾的"HelloWorld"字符串
    DCB    "HelloWorld\n",0
    END                               ;本文件结束
 

  此程序流程如下:首先对一些需要使用的资源进行定义和初始化,包括堆栈指针地址、字符串内存空间、4个寄存器、UART等,然后把字符串(以0结尾)从内存装载到R0,转到子程序Puts,把R0、R1、LR入栈,LR的作用是保存连接数据,待子程序运行完毕即可通过LR回到主程序,子程序Pu将ts先R0数据复制到R1,再将R1中的一个字节复制到R0,若不为0(为0代表到了结尾),则跳转至子程序Putc,Putc的作用是使用UART发送字符串数据,检查缓冲未满后,将UART寄存器地址加载到R1中,再将R0保存的字节数据写入R1,即写入到UART寄存器,即可完成输出,返回至子程序Puts,再通过Putc输送下一个字节数据,直至遇到0,输出完毕,退出至主程序,进入死循环。

posted on 2018-03-09 15:53  黑夜里的黑喵  阅读(717)  评论(0)    收藏  举报

导航