KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记4——Directives
KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记4——Directives
- 一、若干重要的DIRECTIVE介绍
- 二、一些概念
- 三、Directives详细介绍
- 1,GET/INCLUDE 文件包含
- 2, IF...ELSE...ENDIF 条件汇编
- 3, WHILE…ENDW 循环汇编
- 4, DEF 符号/变量定义检查
- 5,GBLA,GBLL,GBLS变量定义
- 6,SETA,SETL,SETS变量赋值
- 7,EQU符号常量赋值
- 8,RLIST寄存器列表定义
- 9,RN寄存器别名
- 10,MACRO…MEND
- 11,ROL、ROR、MOD等运算符
- 12,EXPORT、IMPORT、EXTERN
- 四、一些体会
- 五、参考文件
一、若干重要的DIRECTIVE介绍
在前面的工程中,我感觉下面的这些Directives是非常有用的。
名称 | 功能 |
---|---|
GET/INCLUDE | 包含其他文件 |
IF…ELSE…ENDIF | 类似与条件编译 |
WHILE…ENDW | 重复生成代码、汇编器变量计算 |
DEF | 类似于C中的#ifdef |
GBLA,GBLL,GBLS | 定义汇编器变量 |
SETA,SETL,SETS | 汇编器变量赋值 |
EQU | 符号赋值 |
RLIST | 寄存器列表定义 |
RN | 寄存器别名 |
MACRO…MEND | 宏定义 |
ROL、ROR、MOD等运算符 | 实现汇编器运算 |
EXPORT、IMPORT、EXTERN | 输出/引入符号 |
这里所有的Directives都在《ARM Developer Suite Assembler Guide》可以查到。
这些Directives是在汇编器的第一遍pass的时候被执行的。有点类似C语言的宏。
二、一些概念
三、Directives详细介绍
1,GET/INCLUDE 文件包含
这个就跟C语言下面的include是几乎一样的。可以将其他的可汇编文件内容拷贝到当前的文件里。
GET filename
这里注意GET的文件要可汇编的。所以如果弄个.h文件是不能用的。一般来说,后面的文件都是.s的。比如。
get registers.sget irqn_vector.sget bus_clocks.s
2, IF…ELSE…ENDIF 条件汇编
具体的语法是
IF logical-expression … {ELSE …} ENDIF
注意IF、ELSE和ENDIF都不能顶格写。会被误判成符号。
可以实现条件编辑。比如我这里有一段这样写。就可以实现在设置不同的USART时钟选择的时候,给USART_BSS_VAL这个符号赋不同的值。
if USART_CLOCK_BUSEN = RCC_APB2ENR
USART_BSS_VAL equ (FREQ_APB2 / BAUDRATE / 16 :rol: 4) + ( FREQ_APB2 / BAUDRATE :mod: 16 )else
USART_BSS_VAL equ (FREQ_APB1 / BAUDRATE / 16 :rol: 4) + (FREQ_APB1 / BAUDRATE :mod: 16 ) endif
3, WHILE…ENDW 循环汇编
可以重复开始一段指令序列或directives。
WHILE logical-expression
code
WEND
where: logical-expression is an expression that can evaluate to either {TRUE} or {FALSE}
注意WHILE和ENDW都不能顶个,会被误判成符号。
我用这个指令可以实现一些数值的计算。
gbla nCal_PPRE2_Divgbla nCal_PPRE2_Reg
nCal_PPRE2_Div seta FDIV_APB2 :ror: 1
nCal_PPRE2_Reg seta 0while nCal_PPRE2_Div != 0x01
nCal_PPRE2_Reg seta nCal_PPRE2_Reg + 1
nCal_PPRE2_Div seta nCal_PPRE2_Div :ror: 1wend
nCal_PPRE2_Reg seta nCal_PPRE2_Reg + 0x04
4, DEF 符号/变量定义检查
可以检查某个符号/变量是否在系统中被定义。
DEF :DEF:A {TRUE} if A is defined, otherwise {FALSE}.
用的时候要注意那两个冒号不能漏了。
这个运算符可以配合条件汇编、符号/变量定义实现C头文件中的那种Guard。例如下面这样的编码。先判断是否定义了_REGISTER_S_这个符号/变量。如果没有定义,就用gbll定义一个这样的汇编器变量。
if :def: _REGISTER_S_else gbll _REGISTER_S_
; General Purpose Registers
callee_regs rlist {r4-r12,lr};SCB
SCB_BaseAddr equ 0xE000ED00
SCB_CPUID equ 0xE000ED00
SCB_VTOR equ 0xE000ED08endifend
5,GBLA,GBLL,GBLS变量定义
用于定义变量。必须不能顶格写。
Directive | 功能 |
---|---|
GBLA | 定义一个文内数值变量,初始值为0 |
GBLL | 定义一个文内逻辑变量, 初始值为FALSE |
GBLS | 定义一个文内字符串, 初始值为null |
语法为
gblx variable
where:
gblx is one of GBLA, GBLL, or GBLS.
variable is the name of the variable. variable must be unique amongst symbols within a source file.
用法在前面有出现
6,SETA,SETL,SETS变量赋值
用于给GBLx定义的变量进行赋值。必须顶格写。
Directive | 功能 |
---|---|
SETA | 给一个文内数值变量赋值 |
SETL | 给一个文内逻辑变量赋值 |
SETS | 给一个文内字符串赋值 |
用法在前面已经出现过。
7,EQU符号常量赋值
给常量赋值。语法比较简单。必须顶格写。 一般来说就是:
name EQU expr{, type}
一般后面花括号里面的我不怎么用。详细的查手册吧。
这里说明一点。由于这些Directives都是运行在第一pass的,而指令都是在第二pass的时候被扫描的。所以对于指令里用的立即数,不论是汇编常量还是汇编变量,用法都是一样的。
8,RLIST寄存器列表定义
给一个通用寄存器的集合命名。必须顶格写。 语法是
name RLIST {list-of-registers}
目前我只是用来给函数需要保护的寄存器做个集合,这样在进入函数和离开函数的时候能有个统一一点的写法。
; General Purpose Registers
callee_regs rlist {r4-r12,lr}
在函数里就比较方便。例如下面的这个函数。
area USB_UART_CODE_SECTION, codealign 4
init procpush callee_regs...pop callee_regsbx lrendp
9,RN寄存器别名
给寄存器起别名。必须顶格写。 语法是
name RN expr
; Define the registers commonly used in this file.
rRCC rn r12
rGPIO rn r11
rUART rn r10
rNVIC rn r9
rpBuf rn r8
rBuf_Size rn r7
如果寄存器够用的话,给寄存器起别名可以大大增加汇编代码的可读性。如果不够用的话,就得好好规划一下。但是也不是说就没有机会。
具体应用如下面这段代码。
ldr r0, [rGPIO, #GPIO_MODER]orr r0, #TX_PIN_MODER_VAL :or: RX_PIN_MODER_VALstr r0, [rGPIO, #GPIO_MODER]ldr r0, [rGPIO, #GPIO_PORT_AFIO]orr r0, #RX_PIN_AFIO_VAL:OR:TX_PIN_AFIO_VALstr r0, [rGPIO, #GPIO_PORT_AFIO]
在每个汇编文件中,一个别名只能给一个寄存器,但是反过来不一定。就是说一个寄存器可以有多个别名。
10,MACRO…MEND
可以定义一个类似于C的内联函数或宏函数那样的存在。我叫它是汇编宏。语法是这里打不出来,直接去7-27看就好。
应用如下面这段代码。我定义了一个汇编宏叫wait_for_sr_tc_macro_via_r1 。之后只要在这个文件中需要轮询查sr_tc,就可以用这个宏。
macro
$label wait_for_sr_tc_macro_via_r1
$label.test_sr_tc_mldr r1, [rUART, #USART_SR]tst r1, #USART_SR_TCbeq $label.test_sr_tc_m mendalign 4
send_ch procpush callee_regsload_rUARTldr r2, [rUART, #USART_CR1]orr r2, #USART_CR1_TEstr r2, [rUART, #USART_CR1]
before_send wait_for_sr_tc_macro_via_r1 ; It is important to wait for the tc to be set.; By checking this bit via DEBUG window is not possible; to find if this bit is set or cleared.str r0, [rUART, #USART_DR]
after_sent wait_for_sr_tc_macro_via_r1 ; This is the same as the previous waiting.bic r2, #USART_CR1_TEstr r2, [rUART, #USART_CR1] pop callee_regsbx lrendp
如果宏内需要用到跳转,可以用$label指代调用这个宏的那句的标号。
11,ROL、ROR、MOD等运算符
常用的汇编器可以直接使用的运算指令。具体语法参考手册。这里就是强调2点
- IMPORT和EXTERN进来的符号只能用+和-进行处理,其它的运算符不支持。
- 汇编器的这些运算符的运算顺序和C语言是不同的。所以尽可能使用小括号约束。
- 不要忘了运算符单词两边的冒号。
A1466W: Operator precedence means that expression would evaluate differently in C
以上的这个警告就是提示,如果运算太长并过于复杂,建议用小括号进行限制一下。
12,EXPORT、IMPORT、EXTERN
将本文中的符号引出或引入。这个用的很常见。只是要注意,在外部weak定义的符号,如果你想覆盖它,必须把你在文件中定义的符号用export引出去才能真的覆盖。否则这个符号只是在本文中有效。
四、一些体会
灵活使用Directives,可以实现软件的可配置性,并且可以将很多原来由MCU完成的动作提前在上位机上做好。
本文中做的Keil工程可以从这个链接下载:STDIO-App的Keil工程。
五、参考文件
- 《ARM Developer Suite Assembler Guide》
KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记4——Directives相关推荐
- KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记3——串口Stdio实现
KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记3--串口Stdio实现 一.介绍 任务目标 二.工程创建 三.软件设计 第一步,BSP构建 1, 添加前面的pll_config文件 2 ...
- arm汇编的学习笔记,对比x86和arm(1)-从最简单的函数谈起
最简单的函数 x86下汇编指令 ARM下汇编指令 Hello World x86中汇编指令 ARM汇编 LDM/STM指令 LDMFD 指令 ADR指令: 知识点扩展: ADR ADRL: LDR指令 ...
- ARM汇编指令学习笔记(一)
(一)数据常量定义汇编指令EQU EQU用于为程序中的常量.标号等定义一个有效的字符名称,类似于C语言中的#define,当表达式为32位常量时,可指定表达式的数据类型,CODE16,CODE32,D ...
- arm cef3 linux 编译_【学习笔记】CEF Linux编译
源码编译部分转载:https://bitbucket.org/chromiumembedded/cef/wiki/MasterBuildQuickStart#markdown-header-linux ...
- keil 生成bin找不到afx文件_【学习笔记】Keil不能正确生成.bin文件的解决办法
前段时间我写过如何利用CW.IAR和Keil生成image文件,效果还不错,有些用户反馈挺有帮助的,毕竟待项目开发到最后是需要生成image文件用来量产烧写,我们总不至于到最后使用调试下载吧(不过还别 ...
- Arm技术文档全集合(含AMBA总线,Cortex-A,Contex-M,Cortex-R系列处理器,Arm体系结构,Arm服务器,Mali GPU,Keil 开发等PDF下载)
在这里可以下载到所有Arm技术方面的文档,我们已经为大家归类好资料,方便大家学习!持续更新中,大家可点击右下角的收藏图标收藏本帖,如果大家有补充,欢迎评论~ 首发极术社区 Cortex-A系列处理器 ...
- [ARM] [基础][编译]ARM的浮点功能历史分类和对应的编译选项
前言:ARM编译的时候有很多编译选项和浮点功能相关,要真正理解这些编译选项的选择,不仅仅要了解ARM的体系构建的基础知识,可能还需要了解一下ARM的历史.之后,真对这些再考虑到ARM编译选项就比较好理 ...
- NXP i.MX 8M Plus工业开发板硬件说明书( 四核ARM Cortex-A53 + 单核ARM Cortex-M7,主频1.6GHz)
前 言 本文主要介绍创龙科技TLIMX8MP-EVM评估板硬件接口资源以及设计注意事项等内容. 创龙科技TLIMX8MP-EVM是一款基于NXP i.MX 8M Plus的四核ARM Cortex- ...
- NXP i.MX 8M Plus工业开发板硬件说明书--上册( 四核ARM Cortex-A53 + 单核ARM Cortex-M7,主频1.6GHz)
前 言 本文档主要介绍创龙科技TLIMX8MP-EVM评估板硬件接口资源以及设计注意事项等内容. 创龙科技TLIMX8MP-EVM是一款基于NXP i.MX 8M Plus的四核ARM Cortex ...
最新文章
- Python 为什么要保留显式的 self ?
- DrugVQA | 用视觉问答技术预测药物蛋白质相互作用
- 用户自定义的标识符的一些注意事项
- 选择存储服务器硬盘并解决一些疑问
- java 爬中 验证码识别_JAVA爬虫---验证码识别技术(一)
- oracle有 哪些常用视图,oracle常用视图
- ITK:重新运行管道不断变化的最大可能的地区
- 一起谈.NET技术,Visual Studio与C#编程十个实用技巧
- hdu-6165(tarjan+topusort)
- 价值投资/指标选股(akshare)
- security工作笔记006---oauth2(spring security)报错method_not_allowed(Request method 'GET' not supported)解决
- 3 | Spatial-based GNN/convolution模型之 NN4G
- 修改ASM磁盘组冗余模式(一):copy-switch方式
- java函数式编程例子_java函数式编程Lambda表达式的示例(一)
- 什么是BI(Business Intelligence
- 如何创建从硬盘安装的硬像文件
- 现实世界与虚拟世界的差别在哪里
- 菜鸟教程Python100例-笔记
- python,matlab 读取NIFTI(.nii)格式图像、FSL安装
- python中sys是什么意思_python里的sys是什么意思