• 单片机核心/RTOS必备 (ARM汇编)


    ARM汇编概述

    一开始,ARM公司发布两类指令集:

    1. ARM指令集,这是32位的,每条指令占据32位,高效,但是太占空间。
    2. Thumb指令集,这是16位的,每条指令占据16位,节省空间。

    要节省空间时用Thumb指令,要效率时用ARM指令

    一个CPU既可以运行ARM指令,也可以运行Thumb指令。
    怎么区分当前指令是Thumb还是ARM指令呢?
    程序状态寄存器中有一位,名为“T”,它等于1时表示当前运行的是Thumb指令。

    假设函数A是使用Thumb指令下的,函数B是使用ARM指令写的,怎么调用A/B?
    我们可以往PC寄存器里写入函数A或B的地址,就可以调用A或B。
    但是怎么让CPU在执行A函数时进入Thumb状态,在执行B函数时进入ARM状态?

    做个手脚:
    调用函数时A时,让PC寄存器的BIT0等于1,即PC=函数A地址+(1<<0);
    调用函数时B时,让PC寄存器的BIT0等于0,即PC=函数B地址;

    引入Thumb2指令集,支持16位指令、32位指令混合编程。

    ARM公司推出了:Unified Assembly Language UAL,统一汇编语言,不需要去区分这些指令集。

    UAL汇编格式为:
    Operation {cond} {S} Rd, Rn, Operand2

    • Operation表示各类汇编指令,比如ADD、MOV。
    • cond表示condition,即该指令执行的条件。
    • S表示该指令执行后,会修改程序状态寄存器。
    • Rd为目的寄存器,用来存储运算的结果。
    • Rn、Operand2是两个源操作数。

    立即数

    MOV R0,#VAL
    
    • 1

    意思是把VAL这个值存入R0寄存器。
    VAL可以是任意值吗?
    不可以,必须是立即数。
    假设VAL可以任意数,“MOV R0,#VAL”本身16位或32位,哪来的空间保存任意数值的VAL,所以VAL必须符合某些规定。
    在这里插入图片描述

    LDR伪指令

    去判断一个VAL是否是立即数,麻烦,并且就是想把任意数值赋给R0,怎么办?
    可以使用伪指令:LDR R0,=VAL
    伪指令就是假的,不存在的指令。
    LDR作为伪指令时,指令中有一个=,否则它就是真的LDR指令了。

    编译器会把伪指令替换成真实的指令,比如:
    LDR R0,=0x12
    0x12是立即数,那么替换为 MOV R0,#0x12

    LDR R0,=0x12345678
    0x12345678不是立即数,替换为
    Label DCD 0x12345678 //编译器在程序某个地方保存这个值
    LDR R0,[PC,#offser] //使用Load Register读内存指令读出值,offset是链接程序时确定的。

    ADR伪指令

    用来读某个标号的地址

    ADR R0,Loop
    
    Loop
    	ADD R0,R0,#1
    
    • 1
    • 2
    • 3
    • 4

    它是伪指令,会被转换成某条真实的指令。

    ARM编译器与GCC编译器语法差异

    在这里插入图片描述
    低位存放在低地址,小字节序(little endian)。
    高位存在低地址,大字节序(big endian)。

    程序处理的4个步骤

    在这里插入图片描述
    main.c经过预处理后生成main.i,经过编译后形成汇编文件.s
    汇编文件经过汇编后得到目标文件,多个目标文件链接生成.elf可执行程序(含有机器码),可执行程序再经过反汇编后生成汇编代码.dis。

    汇编:把汇编文件转换成目标文件(里面是机器码)
    反汇编:把可执行文件(目标文件,里面是机器码),转换成汇编文件

    KEIL下怎么反汇编?
    在 KEIL的User选项中,添加这两项:
    在这里插入图片描述
    上电后:
    设置栈:CPU会从0x08000000读取值,用来设置SP
    跳转:CPU会从0x08000004得到地址值,根据它的BIT0切换到ARM状态或者Thumb状态,然后跳转。
    对于Cortex M3/M4,仅支持Thumb状态,所以0x08000004上的值bit0必定是1。
    0x08000004上的值 = Reset_Handler+1
    从Reset_Handler上继续执行

  • 相关阅读:
    阿里云K8s容器Pod中Java进程CPU占比100%排查
    HTML(28)——空间转换
    损失函数总结(五):PoissonNLLLoss、GaussianNLLLoss
    【Linux】ubuntu18.04安装mysql5.7安装失败处理
    python基础语法(八)
    【无标题】
    SQL Server实战六:T-SQL、游标、存储过程的操作
    Linux安装Docker
    今年 A-Level 大考压分?成绩不理想怎么办?
    辛苦复习两个月,线上三面阿里Java高开岗,终如愿拿到offer
  • 原文地址:https://blog.csdn.net/Caramel_biscuit/article/details/134034966