《ASM 程序深度解析 && 串口硬件知识》

建议:最好跟着来一遍,不然的话,纸上谈兵,诋毁一切 !!!

 一、进制知识

10进制里,每一位的权重,从右往左数:个十百千万,也就是:10^0, 10^1, 10^2,10^3……

16进制里,每一位的权重,从右往左数,分别是:16^0, 16^1, 16^2, 16^3, 16^4, ……

  8进制里,每一位的权重,从右往左数,分别是:8^0, 8^1, 8^2, 8^3, 8^4, ……

  2进制里,每一位的权重,从右往左数,分别是:2^0, 2^1, 2^2, 2^3, 2^4, ……

 二、字节序&位操作

  • 0x12345678的低位(0x78)存在低地址,即方式1,叫做小字节序(Little endian);
  • 0x12345678的高位(0x12)存在低地址,即方式2,叫做大字节序(Big endian);  
  • 在嵌入式开发中,我们只涉及逻辑移位:不关心符号位,都是补0
  • 算术移位,需要分有符号型值和无符号型值
  1. 对于无符号型值,算术移位等同于逻辑移位。
  2. 对于有符号型值 ,算术左移等同于逻辑左移;算术右移补的是符号位,正数补0,负数补1。
  • 取反
  • 位于
  • 位或
  • 置位(|=(1<<n))
  • 清位 (&=~(1<<n))

三、汇编_反汇编_机器码 

  •  我们想深入了解ARM架构,想深入了解汇编与C,想深入理解栈的作用,想深入理解C语言的实质,就必须把最终的可执行程序,反汇编后,阅读得到的汇编代码。
  • 汇编:汇编文件转换为目标文件(机器码)
  • 反汇编:可执行文件(目标文件,机器码)转换为汇编文件、
  • KEIL怎么反汇编:
  1. 在KEIL的User选项中,如下图添加这两项:(可能需要改命名)
  2. fromelf  --bin  --output=led.bin  Objects\led_c.axf
  3. fromelf  --text  -a -c  --output=led.dis  Objects\led_c.axf
  4. 然后重新编译,即可得到二进制文件led.bin(以后会分析)、反汇编文件led.dis。
  5. 如下图操作:
  • GCC下反汇编
  1. 使用GCC工具链编译程序时,在Makefile中有一句:
  2. $(OBJDUMP) -D -m arm  led.elf  > led.dis    # OBJDUMP = arm-linux-gnueabihf-objdump
  3. 他就是把可执行程序led.elf,反汇编,得到led.dis
  • 机器码与汇编
  1. 前面介绍过伪指令,伪指令是实际不存在的ARM指令,编译器在编译时转换为存在的ARM指令,我们代码中的ldr r1,=0x????????这条为指令的真实指令是什么呢?
  2. LDR SP, =(0x20000000+0x10000)   // STM32F103
    ldr sp, =(0x80000000+0x100000)  // IMX6ULL
    ldr sp, =0xc0000000 + 0x100000  // STM32MP157 A7
  3. 我们只摘取前面一小段,第一列是地址,第二列是机器码,第三列是汇编:

  •  解析LDR伪指令
  • 为什么PC=当前指令+4或8呢?
  1. CORTEX M3/M4:使用Thumb2指令集,一条指令是16位或32位
  2. CORTEX A7:默认使用ARM指令集,一条指令是32位
  3. 流水线:ARM指令采用流水线机制:1️⃣、当前执行A地址的指令;2️⃣、同时已经在对下一条指令进行译码;3️⃣、同时已经在读取下下一条指令:PC = A + 4(Thumb/Thumb2指令集)、PC = A + 8(ARM指令集)

总结: C:为了方便人类使用,发明的高级语言,要转换为汇编;汇编:为了解放人类的记忆,发明的助记符,不用去记各类机器码,最终要转换为机器码;机器码:给CPU使用 !!!

四、C 与汇编深入分析

 

  •  直接调用:bl main
  •  想传参数怎么办:在arm中有个ATPCS规则,(ARM-THUMB procedure call standard)(ARM-Thumb 过程调用标准):约定 r0 - r15的用途:
  • r0 - r3:传参
  • r4 - r11:局部变量(入口保存,出口恢复)
  • r12 - r13:特殊寄存器
  •  C 函数的反汇编码阅读
  1. 要解决这几个问题:
  2. 为什么调用C函数前要设置栈?栈的作用是?
  3. C函数传参
  4. C函数执行过程体验
  •  Flash 上的内容
  1. 反汇编示例
  2. 烧写在Flash上的内容
  3. 启动流程

    上电后:

    1️⃣、设置栈:CPU会从0x80000000读取值,用来设置SP(我们的程序里再次设置了SP)

    2️⃣、跳转:CPU从0x80000004得到地址值,根据它的Bit0切换为ARM状态或Thumb状态

    然后跳转;

            01、对于cortex M3/M4,它只支持Thumb状态,所以0x08000004上的值bit0必定是1
            02、0x08000004上的值 = Reset_Handler + 1

    3️⃣、从Reset_Handler继续执行

 五、纯汇编点灯(走进汇编的大门)

  •  流程:
  1. 对于寄存器的操作,主要涉及读、修改、写
  2. 读可以使用LDR,写可以使用STR
  3. 清除使用BIC或AND指令,设置位使用ORR指令
  4. 函数条件判断:减一:SUB;但是顺便使用减1后的结果影响程序状态寄存器,代码为`SUBS R0, R0, #1`
  5. 程序的调用与返回

      1️⃣、传参:R0
      
      2️⃣、调用:BL

      3️⃣、返回:MOV PC,LR

  •  但是:中断保存现场多了一个寄存器:PC,一个栈帧,进入异常前,依次把xPSR, PC, LR, R12以及R3-R0由硬件自动压入适当的堆栈中(响应异常时,若当前代码正在使用PSP,则压入PSP,否则就压入MSP),其中,PC(SP-0x24处)即为图中返回地址:
  • 为什么多了PC:()
  • 这样的话,中断返回的时候,就会用 PC - 4 来处理了 !!!(猜测,这里我的理解可能有错+三级流水线,具体问题具体解析)
  •  引用PC是为了存储返回地址,因为发生异常时LR寄存器的特殊性,保存了EXC_RETURN
  • 所以你得认真处理,不明白的是怎么恢复现场

ASM 语言 (星星点灯 程序): 

六、串口硬件知识

  • 要发送数据时,CPU控制内存要发送的数据通过FIFO传给UART单位,UART里面的移位器,依次将数据发送出去,在发送完成后产生中断提醒CPU传输完成。

  • 接收数据时,获取接收引脚的电平,逐位放进接收移位器,再放入FIFO,写入内存。在接收完成后产生中断提醒CPU传输完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值