嵌入式学习札记(基于STM32L431) 一、ARM Cortex | 您所在的位置:网站首页 › 6种寻址方式 › 嵌入式学习札记(基于STM32L431) 一、ARM Cortex |
ARM Cortex-M4微处理器
写在前面ARM Cortex-M4微处理器简介ARM Cortex-M4微处理器内部结构概要位数总线结构中断控制存储器保护低功耗内部寄存器
寻址方式与机器码获取方法指令保留字简表与寻址方式指令保留字简表寻址方式立即数寻址寄存器寻址直接寻址偏移寻址及寄存器间接寻址
机器的指令码运行源文件执行程序所获得的信息
基本指令分类解析数据传送类指令取数指令存数指令寄存器间数据传送指令
汇编语言的基本语法汇编语言的格式标号操作码操作数注释
常用伪指令简介系统预定义的段常量的定义程序中插入常量条件伪指令文件包含伪指令其他常用伪指令
写在前面
本系列学习主要参照了王宜怀老师主编,清华大学出版社出版的《嵌入式技术基础与实践(第六版)》一书,有兴趣的可以自行购买,正版书籍附赠开发版供实验所需 ARM Cortex-M4微处理器简介 ARM Cortex-M4微处理器内部结构概要具体介绍请参考书籍 位数Cortex-M4系列处理器为32位处理器,内部存储器,数据总线均为32位,采用Thumb-2技术,同时支持16位与32位指令 总线结构采用哈佛架构(感兴趣可以自行查阅),统一的存储空间编址,32位寻址,最多支持4GB的存储空间;三级流水线设计;片上接口基于AMBA架构 中断控制采用了集成嵌套向量中断控制器(NVIC),支持8~256个中断优先级,最多240个中断请求 存储器保护可选的MPU 低功耗多种低功耗特性和休眠模式 内部寄存器M4微处理器的寄存器包含用于数据处理与控制的寄存器、特殊功能寄存器与浮点寄存器。特殊功能寄存器有预定义的功能,必须通过专用指令来访问。 寄存器类型序号低位寄存器R0~R7高位寄存器R8~R12SPR13LPR14PCR15PSR(程序状态寄存器)特殊功能寄存器PRIMASK、FAULTMASK、BASEPRI(异常屏蔽寄存器)同上CONTROL(控制寄存器)同上 寻址方式与机器码获取方法CPU可以执行特定功能的操作命令被称为指令 CPU所能执行的各种指令的集合,成为该CPU的指令系统 指令保留字简表与寻址方式 指令保留字简表其他指令请查阅《ARM v7-M 参考手册》 类型保留字含义数据传送类ADR生成与PC指针相关的地址LDR、LDRH、LDRB、LDRSB、LDRSH、LDMIA将存储器中的内容加载到寄存器中STR、STRH、STRB、STMIA将寄存器中的内容存储到存储器中MOV、MVN寄存器间数据传送PUSH、POP进栈出栈数据操作类下为子类算数运算类ADC、ADD、SBC、SUB、MUL加、减、乘指令CMN、CMP比较指令逻辑运算类AND、ORR、EOR、BIC按位与、或、异或、位段清零数据序转类REV、REVSH、REVH反转字节序扩展类SXTB、SXTH、UXTB、UXTH无符号扩展字节、有符号扩展字节……………… 寻址方式 立即数寻址操作数直接通过指令给出。用“#”作为立即数的前导标识符。M4微处理器的立即数范围是0x00~-0xFF。例如: MOV R0, # 0xFF //立即数0xFF装入R0寄存器 SUB R1, R0, # 1 //R1←R0 - 1 寄存器寻址操作数来自寄存器。例如: MOV R0, R1 //将R1寄存器内容装入R0寄存器 直接寻址操作数来自存储单元,指令中直接给出存储单元地址。指令码中显示给出数据的位数,如:字、半字、单字节。例如: LDR Rt, label //从标号label处连续读取4字节到寄存器中 LDRH Rt, label //从地址label处读取半字到Rt中 LDRB Rt, label //从地址label处读取字节到Rt中 偏移寻址及寄存器间接寻址偏移寻址的操作数来自存储单元,指令中通过寄存器及偏移量给出存储单元的地址。偏移量不超过4KB。偏移量为0的偏移寻址也成为寄存器间接寻址。例如: LDR R3, [PC, # 100] //从地址(PC+100)处读取4字节到R3中 LDR R3, [R4] //以R4中内容为地址,读取4字节到R3中 机器的指令码 运行源文件利用开发环境打开工程…\CH02-1。测试代码如下: Label: MOV R0, # 0xDE LDR R0, = data_format1 LDR R1, = Label LDR R2, [R1] BL printf执行结果如下图: 从上图现实的内容可以看出,标号代表的地址为0900D87E,这就是指令MOV R0,# 0xDE机器码要存放的开放地址,各地址存储内容如下表: 地址0800D87E0800D87F0800D8800800D881内容4FF0DE00STM32数据存储采用的是小段模式,即将2个字节以上的一个数据的低字节放在存储器低地址单元,高字节放在高地址单元。 基本指令分类解析 数据传送类指令有两种情况:一是取存储器地址空间中的数传送到寄存器中,二是将寄存器中的数传送到另一寄存器或存储器地址空间中 取数指令 编号指令说明(1)LDR Rt, [< Rn | SP > {, #imm }]从地址{ SP/Rn + # imm}处,取字到Rt中,imm = 0, 4, 8, …, 1020LDR Rt, [Rn, Rm]从地址Rn + Rm处读取字到Rt中LDR Rt, label从标号label指定的存储器单元取数到寄存器,标号label必须在当前指令的-4~4KB范围内,且应4字节对齐(2)LDRH Rt, [Rn {, #imm}]从地址{Rn + #imm}处,取半字到Rt中,imm = 0, 2, 4, …, 62LDRH Rt, [Rn, Rm]从地址Rn + Rm处读取半字到Rt中(3)LDRB Rt, [Rn {, #imm}]从地址{Rn + #imm}处,取半字到Rt中,imm = 0~31LDRB Rt, [Rn, Rm]从地址Rn + Rm处读取字节到Rt中(4)LDRSH Rt, [Rn, Rm]从地址Rn + Rm处读取半字到Rt中,并带符号扩展至32位(5)LDRSB Rt, [Rn, Rm]从地址Rn + Rm处读取字节到Rt中,并带符号扩展至32位(6)LDM Rt{ ! }, reglist从地址Rn处读取多个字, 加载到reglist列表寄存器中,每读一个字后Rn自增一次 存数指令Rt,Rn,Rm必须为R0~R7中的一个 编号指令说明(7)STR Rt, [< Rn | SP > {, #imm }]把Rt中的字存储到地址SP/Rn + #imm处,imm = 0, 4, 8,…, 1020STR Rt, [Rn, Rm]把Rt中的字存储到地址Rn + Rm处(8)STRH Rt, [Rn {, #imm}]把Rt中的低半字存储到地址SP/Rn + #imm处,imm = 0, 2, 4, …, 62STRH Rt, [Rn, Rm]把Rt中的低半字存储到地址Rn + Rm处(9)STRB Rt, [Rn {, #imm}]把Rt中的低字节存储到地址SP/Rn + #imm处,imm = 0~31STRB Rt, [Rn, Rm]把Rt中的低字节存储到地址Rn + Rm处(10)STM Rn!, reglist存储多个字到Rn处,每存一个字后Rn自增一次 寄存器间数据传送指令 编号指令说明(11)MOV Rd, RmRd←Rm,Rd只可以是R0~R7(12)MOVS Rd, # imm功能同MOV, 且影响N、Z标志(13)MVN Rd, Rm将寄存器Rm中的数据取反,传送给寄存器Rd,影响N、Z标志其他指令请参考书籍,在此不再罗列 汇编语言的基本语法汇编语言源程序以行为单位进行设计,每行最多可以包含一下4部分 标号:操作码操作数注释 汇编语言的格式 标号 如果一个语句有标号,则标号必须书写在汇编语句的开头部分可以组成标号的字符有字母A ~ Z、 a ~ z、数字0 ~ 9、下划线(_),美元符号($),但开头的第一个符号不能为数字和 $编译器对标号中字母的大小写敏感,但指令不区分大小标号长度基本不受限制,但实际使用时通常不超过20个字符。标号后必须带冒号(:)一个标号在一个文件(程序)中只能被定义一次,否则出现重复定义,不能通过编译一行语句只能有一个标号,编译器将把当前程序计数器的值赋给该标号 操作码操作码包括指令码和伪指令。 对于有标号的行,必须至少用一个空格或制表符将标号与操作码隔开;对于没有标号的行,不能从第一列开始写指令码,应以空格或制表符开头。 操作数操作数可以使地址,标号或指令码定义的常数,也可以是有伪运算符构成的表达式。 如果一条指令或伪指令有操作数,则操作数与操作码之间必须用空格隔开书写。操作数多于一个的,操作数之间用逗号分隔。操作数也可以是M4内部寄存器,或者另一条指令的特定参数。 操作数一般都有一个存放结果的寄存器,这个寄存器在操作数的最前面 1、常数标识 编译器识别的常数有十进制、十六进制(0x)、二进制(0b) 2、“#”表示立即数 一个常数前添加“#”表示一个立即数;不加“#”时,表示一个地址。 3、圆点 如果圆点(.)单独出现在语句操作码之后的操作数位置上,则代表当前程序计数器的值被放置在圆点的位置。 4、伪运算符 略。详情请查阅资料 注释类似于C语言 常用伪指令简介在CCS开发环境下,所有的汇编命令都是以“.”开头的 系统预定义的段C语言程序在经过gcc编译器最终生成.elf格式的可执行程序。.elf可执行程序是以段为单位来组织文件的。通常划分为如下三个段: .text @只读的代码区 .data @可读可写的数据区 .bss @是可读可写且没有初始化的数据区 常量的定义常量的定义可以使用.equ汇编指令,例如: .equ _NVIC_ICER, 0xE00E180 ... LDR R0, = _NVIC_ICER @将0xE00E180放到R0中常量的定义还可以使用.set汇编指令,例如: .set _NVIC_ICER, 0xE00E180 程序中插入常量 插入数据的类型伪指令字.word半字.hword字节.byte字符串.ascii.asciz LDR R3, = NUMBER LDR R4, [R3] ... LDR R0, = HELLO_TEXT BL PrintText ... ALIGN 4 NUMBER: .word 0x123456789 HELLO_TEXT: .asciz "hello\n" 条件伪指令.if条件伪指令后面紧跟一个恒定的表达式,并且最后要以.endif结尾。中间如果有其他条件,可以用.else编写汇编语句。 .ifdef标号表示如果标号被定义,则执行下面的代码。 文件包含伪指令 .include "filename" 其他常用伪指令(1).section:用户可以通过该指令来自定义一个段 .section .isr_vector, "a" @定义一个.isr_vector段,"a"表示允许段(2).global:用来定义一个全局符号 .global symbol(3).extern:.extern symbol 声明symbol为外部函数,调用时可以遍历所有文件找到该函数并使用 .global main bl main(4).align:通过填充字节使当前位置满足一定的对齐方式 (5).end:声明汇编文件的结束 其余详见《GNU汇编语法》 |
今日新闻 |
推荐新闻 |
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 |