基于Keil a51汇编 —— 标准宏定义
定义标准宏
标准宏定义如下:
macro-name MACRO <[>parameter-list<]>
<[>LOCAL local-labels<]>
.
.
.
macro-body
.
.
.ENDM
macro-name 宏的名称
parameter-list 可以传递给宏的形式参数的可选列表
LOAD_R0 MACRO R0_ValMOV R0, #R0_ValENDM
定义一个名为 LOAD_R0 的宏,该宏使用传递给宏的第一个参数的值加载寄存器 0。
注意:
- 与 MPL 宏不同,一旦定义了标准宏,就可能无法重新定义它。
- 宏可以定义,也可以不带正式参数列表。
- 标准宏定义最多可嵌套 9 个级别。
- 标准宏可以递归调用,深度可达 9 级。
宏参数
宏主体中的参数用参数名称(在上面的示例中为 src、dst 和 cnt)表示。它们可以在宏体内以任意次数和任何顺序使用。如果参数与宏同名并在宏主体中使用,则会展开该参数。不调用宏。
标准宏最多可以有 16 个参数。在宏定义和调用中,参数必须用逗号 (‘,’) 分隔。例如:
mymacro MACRO P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16
您将按如下方式调用此宏:
mymacro A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
您可以通过从宏调用中省略参数来传递参数的 NULL 值。分隔逗号仍然是必需的。例如:
mymacro A,,C,,E,,G,,I,,K,,M,,O,
空参数可以使用无宏运算符。
调用标准宏
下面定义了一个名为 BMOVE 的宏,该宏采用三个参数:源、目标和计数。宏生成的代码将任意数量的字节从内存的一部分复制到另一部分。
BMOVE MACRO src, dst, cnt
LOCAL labMOV R2,#cntMOV R1,#srcMOV R0,#dst
lab: MOV A,@R1MOV @R0,AINC R0INC R1DJNZ R2,labENDM
若要调用此宏,请指定宏名称和参数列表。例如,可以按如下方式调用上述宏:
BMOVE array1, array2, 10
宏扩展为:
MOV R2,#10MOV R1,#array1MOV R0,#array2
??0000: MOV A,@R1MOV @R0,AINC R0INC R1DJNZ R2,??0000
注意:
- 上面的示例会产生程序集错误,因为源文件不包含段定义。
- 这根和玄美指令可用于在汇编程序列表文件中包括宏定义和宏调用。
局部符号(LOCAL)
标准宏可能包括作为分支目标的本地标签。
固定的标签名称会导致错误,如果多次调用宏。发生这种情况是因为同一标签名称在源文件中只能使用一次。此问题可以通过使用局部符号来解决。本地宏符号将替换为唯一的顺序编号标签,该标签在每次调用宏时递增。
下面的示例演示如何使用宏定义中的 LOCAL 语句创建本地标签实验室。
BMOVE MACRO src, dst, cnt
LOCAL labMOV R2,#cntMOV R1,#srcMOV R0,#dst
lab: MOV A,@R1MOV @R0,AINC R0INC R1DJNZ R2,labENDM
注意:
- 必须在紧跟在宏定义后面的行中声明本地标签。
- 一个宏中最多可以定义 16 个本地标签。
退出宏(EXITM)
EXITM 指令立即终止宏扩展。检测到此指令时,宏处理器将停止扩展当前宏,并在下一个 ENDM 指令之后恢复处理。EXITM 指令在条件语句中很有用。例如:
WAIT MACRO X ; macro definitionIF NUL X ; make sure X has a valueEXITM ; if not then exitENDIFREPT X ; generate X NOP instructionsNOPENDM ; end REPT
ENDM ; end MACRO
内置宏
标准宏处理器具有三个内置宏,可以单独使用,也可以在宏定义中使用。它们是:
- 这REPT宏,将块重复指定次数的宏。
- 这IRP宏,为每个指定的参数重复一个块一次。
- 这IRPC宏,为字符串中的每个字符重复一个块一次。
这些内置宏中的每一个都必须以 ENDM 语句终止。
REPT
REPT 内置宏定义如下:
REPT count macro-body
ENDM
- count 是宏观主体展开的次数
- macro-body 是调用宏时展开的文本。
例如:
REPT 5NOP
ENDM
扩展为:
NOPNOPNOPNOPNOP
IRP
IRP 内置宏定义如下:
IRP parm-name, <parm-list>macro-body
ENDM
- parm-name 是宏主体中使用的参数名称。每次展开宏时,都会使用参数列表中的后续值来替换宏主体中的参数名称。
- parm-list 是参数名称替换值的列表。
例如:
IRP regnum, <R0,R1,R2,R3,R4>PUSH A®num
ENDM
扩展为:
PUSH AR0PUSH AR1PUSH AR2PUSH AR3PUSH AR4
IRPC
IRPC 内置宏定义如下:
IRPC parm-name, parm-stringmacro-body
ENDM
parm-name
- List item 是宏主体中使用的参数名称。每次展开宏时,都会使用参数字符串中的后续字符来替换宏主体中的参数名称。
- parm-string 是文本字符串,其字符用于替换宏正文中的参数名称。
例如:
IRPC sendchar, TESTMOV R0, #'sendchar'CALL outchar
ENDM
扩展为:
MOV R0, #'T'CALL outcharMOV R0, #'E'CALL outcharMOV R0, #'S'CALL outcharMOV R0, #'T'CALL outchar
标准宏运算符
有几个运算符可用于标准宏。
| 符号 | 描述 |
|---|---|
| NUL | NUL 运算符用于确定宏参数是否为 NULL |
| & | 与号运算符用于连接文本和参数 |
| <> | 尖括号运算符用于文字化逗号和空格等分隔符 |
| % | 百分号运算符用于表示解释为表达式的宏参数 |
| ;; | 双分号运算符指示应忽略该行的后续文本 |
| ! | 感叹号运算符用于表示文字字符 |
NUL 运算符
当宏调用中省略形式参数时,将为其分配值 NULL。可以通过在宏的 IF 控制语句中使用 NUL 运算符来检查 NULL 参数。
NUL 运算符需要一个参数。如果未找到参数,NUL 将返回值 0。
EXAMPLE MACRO XIF NUL XEXITMENDIFNOPENDMEXAMPLE ; Invoke the macro with no parameters
;Nothing is output since the macro exits (because the x parameter is NULL)
注意:
- 空白字符 (’ ') 的 ASCII 值为 20h,不等同于 NULL。
& 运算符
与号运算符 (‘&’) 可用于连接文本和宏参数,如以下示例所示:
MAK_NOP_LABEL MACRO XLABEL&X: NOPENDM
此宏为每个调用插入一个新标签和一个 NOP 指令。传递给宏的参数将追加到文本 LABEL 中,以便为每行创建标签。例如:
LOC OBJ LINE SOURCE1 MAK_NOP_LABEL MACRO X2 LABEL&X: NOP3 ENDM456 MAK_NOP_LABEL 1
0000 00 7+1 LABEL1: NOP8 MAK_NOP_LABEL 2
0001 00 9+1 LABEL2: NOP10 MAK_NOP_LABEL 3
0002 00 11+1 LABEL3: NOP12 MAK_NOP_LABEL 4
0003 00 13+1 LABEL4: NOP1415 END
<> 运算符
尖括号字符(“<”、“>”)将应按字面传递到宏的文本括起来。某些字符(如逗号 (‘,’)必须括在尖括号中才能传递给宏。
下面的示例演示在尖括号内传递参数列表的宏声明和调用。
1 FLAG_CLR MACRO FLAGS
2 MOV A, #0
3 IRP F, <FLAGS>
4 MOV FLAG&F, A
5 ENDM
6 ENDM
7
8 DSEG
0000 9 FLAG1: DS 1
0001 10 FLAG2: DS 1
0002 11 FLAG3: DS 1
0003 12 FLAG4: DS 1
0004 13 FLAG5: DS 1
0005 14 FLAG6: DS 1
0006 15 FLAG7: DS 1
0007 16 FLAG8: DS 1
0008 17 FLAG9: DS 1
18
19 CSEG
20
21 FLAG_CLR <1>
0000 7400 22+1 MOV A, #0
23+1 IRP F, <1>
24+1 MOV FLAG&F, A
25+1 ENDM
0002 F500 26+2 MOV FLAG1, A
27 FLAG_CLR <1,2,3>
0004 7400 28+1 MOV A, #0
29+1 IRP F, <1,2,3>
30+1 MOV FLAG&F, A
31+1 ENDM
0006 F500 32+2 MOV FLAG1, A
0008 F501 33+2 MOV FLAG2, A
000A F502 34+2 MOV FLAG3, A
35 FLAG_CLR <1,3,5,7>
000C 7400 36+1 MOV A, #0
37+1 IRP F, <1,3,5,7>
38+1 MOV FLAG&F, A
39+1 ENDM
000E F500 40+2 MOV FLAG1, A
0010 F502 41+2 MOV FLAG3, A
0012 F504 42+2 MOV FLAG5, A
0014 F506 43+2 MOV FLAG7, A
在前面的示例中,声明了 FLAG_CLR 宏以清除多个标志变量中的任何一个。FLAGS 参数指定第 3 行中的 IRP 指令使用的参数列表。IRP 指令重复指令 MOV FLAG&F,A 表示 FLAGS 参数中的每个参数。
FLAG_CLR宏在第 21、27 和 35 行中调用。在第 21 行中,只传递一个参数。在第 27 行中传递三个参数,在第 35 行中传递四个参数。参数列表括在尖括号中,因此可以将其称为单个宏参数 FLAGS。宏生成的代码位于第 26、32-34 和 40-43 行。
& 运算符
百分比运算符 (‘%’) 用于将表达式的值传递给宏,而不是传递文本表达式本身。下面的示例演示一个宏定义,该定义需要一个数值以及使用百分比运算符将表达式的值传递给宏的宏调用。
OUTPORT MACRO NMOV R1, #NENDMRESET_SIG EQU 0FFh
CLEAR_SIG EQU 0OUTPORT %(RESET_SIG AND NOT 11110000b)
; Expands into MOV R1, #15OUTPORT %(CLEAR_SIG OR 11110000b)
; Expands into MOV R1, #240
无法将突出显示的行中计算的表达式传递给宏,因为宏需要数值。此类表达式必须在宏之前计算。百分比运算符强制汇编程序生成一个数值,然后将其传递给宏。
;; 运算符
双分号运算符 (‘;;’) 用于指示在展开宏时不应输出行上的其余文本。此运算符通常用于在宏扩展中不需要的注释之前。例如:
MOV_R_A MACRO n ;; helper macroMOV R&n,A ;; set R# to 0ENDMREGCLR MACRO CNTREGNUM SET 0MOV A, #0 ;; load A with 0REPT CNT ;; rpt for CNT registersMOV_R_A %REGNUM ;; set R# to 0REGNUM SET REGNUM+1ENDMENDM
! 运算符
感叹号运算符 (‘!’) 用于指示要按字面方式将特殊字符传递给宏。使用此运算符,可以将逗号 (‘,’) 和尖括号字符(‘<’ 和 ‘>’)(通常被解释为分隔符)传递给宏。
相关文章:
基于Keil a51汇编 —— 标准宏定义
定义标准宏 标准宏定义如下: macro-name MACRO <[>parameter-list<]> <[>LOCAL local-labels<]> . . . macro-body . . .ENDMmacro-name 宏的名称 parameter-list 可以传递给宏的形式参数的可选列表 LOAD_R0 MACRO R0_ValMOV R0, #R0_…...
遍历List集合
1.初始化 // 写法一 List<String> list new ArrayList<>(); list.add("a"); list.add("b"); list.add("c");// 写法二 List<String> list new ArrayList(){{add("a");add(&quo…...
k8s containerd查看镜像
直接查看crictl image会报错: 1) crictl config runtime-endpoint unix:///run/containerd/containerd.sock 2) vi /etc/crictl.yaml 3) systemctl daemon-reload 此时,再查看image:...
acwing.893. 集合-Nim游戏(博弈论sg函数模板)
给定 n� 堆石子以及一个由 k� 个不同正整数构成的数字集合 S�。 现在有两位玩家轮流操作,每次操作可以从任意一堆石子中拿取石子,每次拿取的石子数量必须包含于集合 S�,最后无法进行操作的人视…...
数据安全防护:云访问安全代理(CASB)
云访问安全代理(Cloud Access Security Broker,CASB),是一款面向应用的数据防护服务,基于免应用开发改造的配置方式,提供数据加密、数据脱敏功能。数据加密支持国密算法,提供面向服务侧的字段级…...
面试准备-操作系统
参考: 《程序员面试笔试宝典》(何昊、叶向阳) 进程是系统进行资源分配和调度的一个独立单位。线程是进程的一个实体,是cpu调度和分配的基本单位。线程基本不拥有系统资源,只拥有必须的,但是同属于一个进程…...
深度学习基础知识 Batch Normalization的用法解析
深度学习基础知识 Batch Normalization的用法解析 import numpy as np import torch.nn as nn import torchdef bn_process(feature, mean, var):feature_shape feature.shapefor i in range(feature_shape[1]):# [batch, channel, height, width]feature_t feature[:, i, :,…...
Centos7安装MongoDB7.xxNoSQL数据库|设置开机启动(骨灰级+保姆级)
一: mongodb下载 MongoDB 社区免费下载版 MongoDB社区下载版 [rootwww tools]# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-7.1.0-rc4.tgz 二: 解压到指定目录 [rootwww tools]# mkdir -p /usr/local/mongodb [rootwww tools]# tar -zxvf mongodb-…...
JDK、JRE、JVM三者之间的关系
1.JDK 基本介绍 1) JDK 的全称 (Java Development Kit Java 开发工具包 ) JDK JRE java 的开发工具 [java, javac,javadoc,javap 等 ] 2) JDK 是提供给 Java 开发人员使用的,其中包含了 java 的开发工具,也包括了 JRE 。所以安装了 JDK ,就…...
【ppt技巧】批量修改ppt中的字体
PPT文件中的字体想要全部更换,有什么方便的方法吗?今天分享两个方法,一键修改ppt文件字体。 方法一: 找到功能栏中的编辑选项卡,点击替换 – 替换字体,在里面选择我们想要替换的字体就可以了。 方法二&am…...
RustDay01——运行在线GitHub Rust环境
1.跟着教程进入GitHub教室 2. 授权确认后进入学习空间 3.点击链接进入在线平台 4.添加本机密钥对到GitHub 5. 安装依赖 我们使用在线的Linux试验平台,就自动帮我们clone好了仓库 我们直接在仓库目录执行 cargo install --force --path . 安装依赖 PS:其实刚开始…...
上门按摩小程序|同城上门按摩软件开发|上门按摩系统;
上门按摩小程序的开发具有许多优势,下面就给大家介绍下按摩小程序功能: 上门按摩小程序的优势 方便快捷:上门按摩小程序提供在线预约服务,用户可以通过手机随时随地预约按摩师上门服务,避免了传统预约方式的繁琐和不确定性。 个性…...
rpm安装mysql8后碰到的问题
1 mysqld 无法启动 原因 已经使用了3306端口,修改my.cnf中端口为3308 2 修改为3308端口后,还是无法启动, 2023-10-07T02:20:10.096689Z 0 [ERROR] [MY-010262] [Server] Cant start server: Bind on TCP/IP port: Permission denied 2023…...
Linux 磁盘管理+实例
目录 一、文件系统 二、添加磁盘 三、查看磁盘信息(块设备) 四、分区 1、格式 1)MBR分区 2)GPT分区 2、管理分区 1)使用fdisk 2)使用gdisk 3)使用parted a.交互式 b.非交互式 3、…...
MongoDB——centOS7安装mongodb5.0.21版本服务端(图解版)
目录 一、mongodb官网下载地址二、安装步骤2.1、上传安装包并解压2.2、配置环境变量2.3、创建目录并授权2.4、创建配置文件2.5、启动MongoDB 三、开放端口四、客户端连接 一、mongodb官网下载地址 mongodb官网下载地址:https://www.mongodb.com/try/download/commu…...
C#实现OPC DA转OPC UA服务器
运行软件前提前安装好OPC运行组件: 为方便演示,提前准备好了一个DAServer服务器: 接下来开始配置: 该软件主要实现的功能如下: 配置过程也相对简单: 第一步: 编辑如下文件: 第二步…...
TCP/IP网络协议通信函数接口
创建套接字函数 socket 【头文件】 #include <sys/types.h> #include <sys/socket.h> 【函数原型】 int socket(int domain, int type, int protocol); 【函数功能】 socket 函数创建一个通信端点,并返回一个引用该端点的文件描述符,…...
go语言判断管道是否关闭的误区
前言 本文是探讨的是"在Go语言中,我们是否可以使用读取管道时的第二个返回值来判断管道是否关闭?" 样例 在Go语言中,我们是否可以使用读取管道时的第二个返回值来判断管道是否关闭? 可以看下面的代码 package mainimport "fmt"…...
如何轻松使用 ChatGPT 进行论文大纲和创作
ChatGPT能够编写复杂的代码、博客文章等,它可以帮助我们做很多事情。今天本篇文章分享的主要内容如何利用 ChatGPT 来撰写论文文章。下面会介绍如何轻松使用 ChatGPT 进行论文大纲和创作! 1、使用 ChatGPT 确定主题 文章非常重要的一个部分就是主题。如…...
【深蓝学院】手写VIO第6章--视觉前端--笔记
第5章相关内容,还是CSDN的传统Markdown编辑器好用。 视觉前段在14讲课程中已经讲过,这里再简单复习一下。 1. 前端工作的定性比较,分析 这一节讲了很多关于前端的方法框架的对比讨论,后面看完了相关的论文之后强烈建议再回来听一…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
从零手写Java版本的LSM Tree (一):LSM Tree 概述
🔥 推荐一个高质量的Java LSM Tree开源项目! https://github.com/brianxiadong/java-lsm-tree java-lsm-tree 是一个从零实现的Log-Structured Merge Tree,专为高并发写入场景设计。 核心亮点: ⚡ 极致性能:写入速度超…...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...
Java多线程实现之Runnable接口深度解析
Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...
C++11 constexpr和字面类型:从入门到精通
文章目录 引言一、constexpr的基本概念与使用1.1 constexpr的定义与作用1.2 constexpr变量1.3 constexpr函数1.4 constexpr在类构造函数中的应用1.5 constexpr的优势 二、字面类型的基本概念与使用2.1 字面类型的定义与作用2.2 字面类型的应用场景2.2.1 常量定义2.2.2 模板参数…...
