• ARM开发入门与汇编基础


    2019-12-12

    关键字:汇编指令基础


    首先 ARM 是一家公司,它成立于 1990 年。ARM 公司主要是设计 ARM 系列的 RISC 处理器内核,并将这些内核授权给合作伙伴进行生产与销售。ARM 公司是一家只负责设计内核而不生产芯片的公司。

    ARM 芯片的产品线主要分为三种:

    1、应用级

    应用于高端产品的芯片,如智能手机等。其芯片代号为 A 系列,如 Cortex-A8 , Cortex-A9。

    2、实时嵌入式

    应用于一些对性能要求稍低一些的设备。其芯片代号为 R 系列,如 Cortext-R4。

    3、MCU、FPGA

    主要应用于对成本要求较高但性能要求较弱的产品。其芯片代号为 Cortext-M 系列。

    ARM 的体系架构主要有以下四种:

    1、ARMv4

    2、ARMv5

    3、ARMv6

    4、ARMv7

    不同体系架构拥有不同的指令集。

    一个典型的 ARM 设备至少需要包含三个模块:1、FLASH;2、内存;3、CPU。

    FLASH 负责存储程序,内存负责临时管理程序的运行状态而CPU则负责做计算处理。

    CPU 中又有三个很重要的组成:1、控制器;2、运算器;3、寄存器。

    控制器负责去 FLASH 中准确读取程序内容。运算器负责执行程序代码,或者说负责执行计算需求,而寄存器则负责存储需要计算的数据。

    什么是交叉编译工具链?

    交叉编译工具链是嵌入式行业常听的词汇。嵌入式设备的芯片通常都是 ARM 架构的,而我们用于开发嵌入式程序的电脑却通常都是 X86 架构的。两种芯片架构不同,所编译出来的程序自然也不能通用。那为了能在电脑上编译出嵌入式设备能用的程序来,就必须要用到这个交叉编译工具链了。它的作用就类似于一个“翻译官”,将在电脑上写的代码翻译成能在 ARM 架构的芯片上运行的程序出来。

    ARM 的工作模式

    ARM 主要有七种工作模式:

    1、User

    非特权模式,或者称为普通模式。大部分的任务执行都在这一模式下完成。

    2、FIQ

    中断模式(Fast)。当一个高优先级的中断发生时,就会进入这个模式。

    3、IRQ

    中断模式(normal)。当一个低优先级的中断发生时,就会进入这个模式。

    4、Supervisor

    超级用户模式。当复位或软中断指令执行时会进入这种模式。

    5、Abort

    当需要存取异常信息时会进入这个模式。

    6、Undef

    当执行未定义指令时会进入这个模式。

    7、System

    几乎与 User 模式一样,只是其权限会比 User 稍高一些。

    ARM 有 37 个寄存器,其中 1 个是 PC 寄存器,1个是CPSR(Currnet program status register)寄存器,5个是SPSR(Saved program status register)寄存器以及30个通用寄存器。

    汇编指令基础

    MOV指令

    MOV指令就是 move 的缩写。它表示移动寄存器的值的意思。

     

    mov r1,#13

    mov r2,#0xff

    以上两条指令表示将十进制数值 13 寄存到 r1 寄存器中以及将十六进制数值 0xff 寄存到 r2 寄存器中。

     

    mov r1,r2,LSL#2

    这条指令表示将寄存器 r2 中的值向左移动两位以后再寄存到 r1 寄存器中。LSL 即 left shift logic 的缩写。 假设 r2 寄存器中的值是1,那么指执行了这条指令以后 r1 中的值将会是 4。与之相对应的还有 LSR#2,表示向右移动2位。

     

    MRS 指令

    MOV指令只能操作普通的寄存器,如果要操作特殊寄存器,就得使用 MRS 指令。

     

    mrs r1,cpsr

    mrs cpsr,r0

    以上两条指令分别表示将 CPSR 寄存器中的值读取到普通寄存器 r1 中以及将普通寄存器 r0 中的值写入到 CPSR 寄存器中。

     

    逻辑指令

    and

    逻辑与,例如 and r0,r1 #0xff 相当于 r0 = r1 & 0xff。

     

    orr

    逻辑或,例如 orr r3,r0,#0xf 相当于 r3 = r0 | 0xf。

     

    cmp

    比较。 例如 cmp r1,r0,比较 r1 与 r0 是否相等。

     

    bic

    清除指令。例如 bic r0,r0,#0x03。清除 r0 寄存器中的第 0 号位与第 3 号位。

     

    tst

    测试。例如 tst r0,#0x20。用于测试第 6 位的值是否为0,为0则Z标志位置1。

     

    算术指令

    add

    加法指令。例如:add r0,r1,r2 表示将 r1 与 r2 两寄存器的值相加后保存在 r0 寄存器中。

     

    sub

    减法指令。例如:sub r0,r1,#3 表示将 r1 寄存器中的值减 3 后保存在 r0 寄存器中。

     

    mul

    乘法指令。例如: mul r0, r1, r2 表示将 r1 与 r2 中的值相乘后保存到 r0 寄存器中。

     

    跳转指令

    b

    普通跳转指令。常见的用法为: b label。表示将程序指针跳转到标签为 label 的代码处。即 C 语言中的 goto 语句。

     

    bl

    记忆跳转指令。常见用法为: bl func。这条指令会将下一条指令的地址保存到 LR 寄存器,然后将程序指针跳到 func 标签处执行。待 func 标签处的代码全部执行完毕后可以通过 mov pc,lr 指令将程序指针跳回到先前跳转func前的位置继续执行。这就是单片机中的中断的概念,执行完以后还要回来的那种。

     

    beq

    bne

     

     以下是一个实例,将一段普通 C 语言程序翻译成汇编语言:

    void main()
    {
        int ret = 0;
        func1(2);
        while(1);
    }
    
    int func1(int a)
    {
        if(a == 2)
            return func2(a);
        else
            return func3(a);
    }
    
    int func2(int a)
    {
        return a+3;
    }
    
    int func3(int a)
    {
        return a-1;
    }
    .text
    
    main:
        mov r5,#0
        mov r0,#2
        b1 func1
    main_end:
        b main_end
    
    
    func1:
        mov r12,lr
        cmp r0,#2
        bleq func2
        blne func3
    func_end:
        mov pc,r12
    
    
    func2:
        add r0,#3
        mov pc,lr
    func2_end:
    
    
    func3:
        sub r0,r0,#1
        mov pc,lr
    func3_end:
    
    
    .end

    Load/Store 指令

    load/store 架构规定,存储器之间不能直接拷贝,必须通过CPU中的寄存器作中转。

    load指令的汇编语句为: ldr。它的作用是将指定地址中的数据加载进CPU的寄存器中。

    例如:

    ldr r0,=buf

    ldr r1,[r0]

    第一句的意思是将 'buf' 标签的地址存到 r0 寄存器中。其中 buf 标签是定义在 .data 区段的 .byte 数组。

    第二句的意思就是将 r0 寄存器中的值作为地址,将这个地址中的内容加载到 r1 寄存器中。

     

    ldr r1,[r0,#8]  相当于C语言的 r0 = *(r0 + 8)

     

    store指令的汇编语句为:str。与 ldr 相反,将CPU寄存器中的值写到指定地址中的内存中去。

    例如:

    mov r0,#9

    mov r1,=dest_buf

    str r0,[r1]

    第一句先准备好一个寄存器中的数据。

    第二句确定好内存中的数据段地址。

    第三句将 r0 寄存器中的数据输出到 dest_buf 内存段中去。

     

    GNU汇编伪指令

    GNU汇编伪指令是辅助汇编程序编程用的指令,它不参与实际代码逻辑的构建,仅作辅助标识之用。

    .text  将定义符开始的代码编译到代码段

    .end  文件结束

    .data  将定义符开始的代码编译到数据段

    .equ  定义宏

    .byte  定义1个字节的变量,定义字节数组的指令为: .byte 0x11,'a',0

    .word  定义word变量,长度为4个字节。

    .string  定义字符串,如  .string "hello worl"

    .global  声明全局符号,如 .global =start

     

    批量操作指令

    前面提到的 ldr 与 str 指令都是单寄存器操作的。如果想要一次性操作多个寄存器,则可以使用以下指令

    ldmia 与 stmia。

    例如:

    ldmia r0!,{r7 - r10}。这条指令执行完毕后,会自动将 r7 ~ r10 寄存器中的数据加载到 r0 ~ r3 寄存器中。

    stmia r0!,{r7 - r10}。与上一条指令相反。

     

    堆栈操作指令

    stmfd sp!,{r0 - r12,lr}  将寄存器 r0 ~ r12 lr中的值存入栈中,常用于中断保护现场,'!' 号表示会自动偏移。

    ldmfd sp1,{r0-r12,pc}^  与上一条指令相反,常用于中断恢复现场。

     

    软中断

    swi

    该指令可以产生一个软中断,用法为:swi 0x02,表示产生一个中断号为 2 的软中断。

    2



  • 相关阅读:
    crtmpserver流媒体服务器的介绍与搭建
    RTMP流媒体服务器 crtmpserver
    red5-server源码:https://github.com/Red5/red5-server
    C++实现RTMP协议发送H.264编码及AAC编码的音视频
    linux 下Time_wait过多问题解决
    Tomcat调优配置技巧集锦
    Tomcat调优总结
    LeetCode题解之 Longest Common Prefix
    LeetCode题解之Longest Continuous Increasing Subsequence
    LeetCode题解之Longest Increasing Subsequence
  • 原文地址:https://www.cnblogs.com/chorm590/p/11816196.html
Copyright © 2020-2023  润新知