当前位置: 首页 > news >正文

基于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&regnum
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

标准宏运算符

有几个运算符可用于标准宏。

符号描述
NULNUL 运算符用于确定宏参数是否为 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汇编 —— 标准宏定义

定义标准宏 标准宏定义如下&#xff1a; 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&#xff08;"a"&#xff09;;add&#xff08;&quo…...

k8s containerd查看镜像

直接查看crictl image会报错&#xff1a; 1) crictl config runtime-endpoint unix:///run/containerd/containerd.sock 2) vi /etc/crictl.yaml 3) systemctl daemon-reload 此时&#xff0c;再查看image:...

acwing.893. 集合-Nim游戏(博弈论sg函数模板)

给定 n&#xfffd; 堆石子以及一个由 k&#xfffd; 个不同正整数构成的数字集合 S&#xfffd;。 现在有两位玩家轮流操作&#xff0c;每次操作可以从任意一堆石子中拿取石子&#xff0c;每次拿取的石子数量必须包含于集合 S&#xfffd;&#xff0c;最后无法进行操作的人视…...

数据安全防护:云访问安全代理(CASB)

云访问安全代理&#xff08;Cloud Access Security Broker&#xff0c;CASB&#xff09;&#xff0c;是一款面向应用的数据防护服务&#xff0c;基于免应用开发改造的配置方式&#xff0c;提供数据加密、数据脱敏功能。数据加密支持国密算法&#xff0c;提供面向服务侧的字段级…...

面试准备-操作系统

参考&#xff1a; 《程序员面试笔试宝典》&#xff08;何昊、叶向阳&#xff09; 进程是系统进行资源分配和调度的一个独立单位。线程是进程的一个实体&#xff0c;是cpu调度和分配的基本单位。线程基本不拥有系统资源&#xff0c;只拥有必须的&#xff0c;但是同属于一个进程…...

深度学习基础知识 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 开发人员使用的&#xff0c;其中包含了 java 的开发工具&#xff0c;也包括了 JRE 。所以安装了 JDK &#xff0c;就…...

【ppt技巧】批量修改ppt中的字体

PPT文件中的字体想要全部更换&#xff0c;有什么方便的方法吗&#xff1f;今天分享两个方法&#xff0c;一键修改ppt文件字体。 方法一&#xff1a; 找到功能栏中的编辑选项卡&#xff0c;点击替换 – 替换字体&#xff0c;在里面选择我们想要替换的字体就可以了。 方法二&am…...

RustDay01——运行在线GitHub Rust环境

1.跟着教程进入GitHub教室 2. 授权确认后进入学习空间 3.点击链接进入在线平台 4.添加本机密钥对到GitHub 5. 安装依赖 我们使用在线的Linux试验平台&#xff0c;就自动帮我们clone好了仓库 我们直接在仓库目录执行 cargo install --force --path . 安装依赖 PS:其实刚开始…...

上门按摩小程序|同城上门按摩软件开发|上门按摩系统;

上门按摩小程序的开发具有许多优势&#xff0c;下面就给大家介绍下按摩小程序功能: 上门按摩小程序的优势 方便快捷&#xff1a;上门按摩小程序提供在线预约服务&#xff0c;用户可以通过手机随时随地预约按摩师上门服务&#xff0c;避免了传统预约方式的繁琐和不确定性。 个性…...

rpm安装mysql8后碰到的问题

1 mysqld 无法启动 原因 已经使用了3306端口&#xff0c;修改my.cnf中端口为3308 2 修改为3308端口后&#xff0c;还是无法启动&#xff0c; 2023-10-07T02:20:10.096689Z 0 [ERROR] [MY-010262] [Server] Cant start server: Bind on TCP/IP port: Permission denied 2023…...

Linux 磁盘管理+实例

目录 一、文件系统 二、添加磁盘 三、查看磁盘信息&#xff08;块设备&#xff09; 四、分区 1、格式 1&#xff09;MBR分区 2&#xff09;GPT分区 2、管理分区 1&#xff09;使用fdisk 2&#xff09;使用gdisk 3&#xff09;使用parted a.交互式 b.非交互式 3、…...

MongoDB——centOS7安装mongodb5.0.21版本服务端(图解版)

目录 一、mongodb官网下载地址二、安装步骤2.1、上传安装包并解压2.2、配置环境变量2.3、创建目录并授权2.4、创建配置文件2.5、启动MongoDB 三、开放端口四、客户端连接 一、mongodb官网下载地址 mongodb官网下载地址&#xff1a;https://www.mongodb.com/try/download/commu…...

C#实现OPC DA转OPC UA服务器

运行软件前提前安装好OPC运行组件&#xff1a; 为方便演示&#xff0c;提前准备好了一个DAServer服务器&#xff1a; 接下来开始配置&#xff1a; 该软件主要实现的功能如下&#xff1a; 配置过程也相对简单&#xff1a; 第一步&#xff1a; 编辑如下文件&#xff1a; 第二步…...

TCP/IP网络协议通信函数接口

创建套接字函数 socket 【头文件】 #include <sys/types.h> #include <sys/socket.h> 【函数原型】 int socket(int domain, int type, int protocol); 【函数功能】 socket 函数创建一个通信端点&#xff0c;并返回一个引用该端点的文件描述符&#xff0c;…...

go语言判断管道是否关闭的误区

前言 本文是探讨的是"在Go语言中&#xff0c;我们是否可以使用读取管道时的第二个返回值来判断管道是否关闭?" 样例 在Go语言中&#xff0c;我们是否可以使用读取管道时的第二个返回值来判断管道是否关闭? 可以看下面的代码 package mainimport "fmt"…...

如何轻松使用 ChatGPT 进行论文大纲和创作

ChatGPT能够编写复杂的代码、博客文章等&#xff0c;它可以帮助我们做很多事情。今天本篇文章分享的主要内容如何利用 ChatGPT 来撰写论文文章。下面会介绍如何轻松使用 ChatGPT 进行论文大纲和创作&#xff01; 1、使用 ChatGPT 确定主题 文章非常重要的一个部分就是主题。如…...

【深蓝学院】手写VIO第6章--视觉前端--笔记

第5章相关内容&#xff0c;还是CSDN的传统Markdown编辑器好用。 视觉前段在14讲课程中已经讲过&#xff0c;这里再简单复习一下。 1. 前端工作的定性比较&#xff0c;分析 这一节讲了很多关于前端的方法框架的对比讨论&#xff0c;后面看完了相关的论文之后强烈建议再回来听一…...

用例图 UML从入门到放弃系列之三

1.说明 关于用例图&#xff0c;这篇文章我将直接照搬罗伯特.C.马丁老爷子在《敏捷开发》一书种的第17章&#xff0c;并配上自己的理解&#xff0c;因为这一章写的实在是太精彩了&#xff0c;希望能够分享给大家&#xff0c;共勉。以下是老爷子的原文中文翻译以及豆芽的个人解读…...

NLP大模型

大模型 1、大模型的模型结构 一般指一亿参数以上的模型。 目前以Transformer为基础自回归生成大致可以分为三种架构: Encoder-only的模型,如BERT Encoder-Decoder的模型,如T5。 Decoder-Only的模型,如GPT系列。...

Python- 将一个字符串列表连接成一个单独的字符串

Python中一个常用的技巧&#xff1a;将一个字符串列表连接成一个单独的字符串。 ,.join(list) 是使用Python的 str.join() 方法。 详细解析&#xff1a; join() 方法: 是一个字符串方法&#xff0c;意味着在一个字符串上调用它。它需要一个参数&#xff0c;通常是一个列表或任…...

深眸科技自研AI视觉分拣系统,实现物流行业无序分拣场景智慧应用

在机器视觉应用环节中&#xff0c;物体分拣是建立在识别、检测之后的一个环节&#xff0c;通过机器视觉系统对图像进行处理&#xff0c;并结合机械臂的使用实现产品分类。 通过引入视觉分拣技术&#xff0c;不仅可以实现自动化作业&#xff0c;还能提高生产线的生产效率和准确…...

吴恩达《微调大型语言模型》笔记

微调&#xff08;fine-tuning&#xff09;就是利用特有数据和技巧将通用模型转换为能执行具体任务的一种方式。例如&#xff0c;将 GPT-3 这种通用模型转换为诸如 ChatGPT 这样的专门用于聊天的模型。或者将 GPT-4 转换为诸如 GitHub Coplot 这样的专门用于写代码的模型。 这里…...

Java中的Servlet

Java中的Servlet 在Java中&#xff0c;Servlet是一种用于处理Web请求的服务器端组件。Servlet生命周期是Servlet在运行时所经历的一系列阶段&#xff0c;每个阶段都调用特定的方法。以下是Servlet生命周期内调用的方法过程&#xff1a; 初始化阶段&#xff08;Initialization&…...

Flutter配置Android SDK路径

在使用VSCode作为开发Flutter的工具时&#xff0c;当选择调试设备时&#xff0c;通常看不到android的模拟器&#xff0c;只能看到Chrome之类的。 原因就是Flutter找不到Android的SDK路径&#xff0c;所以无法识别模拟器&#xff0c;我们用flutter doctor命令检查环境时&#xf…...

jwt的基本介绍

说出我的悲惨故事给大家乐呵乐呵&#xff1a;公司刚来了一个实习生&#xff0c;老板让他写几个接口给我&#xff0c;我页面还没画完呢。他就把接口给我了&#xff0c;我敲开心&#xff0c;第一次见这么高效率的后端。但我很快就笑不出来了。他似乎不知道HTTP通信是无状态的。他…...

常见Vue事件修饰符浅析

一、.stop修饰符 .stop修饰符代表event.stopPropagation()&#xff0c;加上这个修饰符&#xff0c;就等于在方法中加上了这句代码。 <!--阻止单击事件继续传播--> <a click.stop"doThis"></a>上面的代码等同于如下代码。 <!--阻止单击事件继…...

怎样开始用selenium进行自动化测试?

如果您刚开始使用 Selenium 进行自动化测试&#xff0c;以下是建议的步骤。 1、安装 Selenium 首先&#xff0c;您需要安装 Selenium。Selenium 支持多种编程语言&#xff0c;如 Python、Java、C# 等。可以通过 pip 命令在 Python 中安装 Selenium&#xff1a; pip install …...