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

基于Keil a51汇编 —— MPL 宏定义

MPL 宏

Ax51汇编程序支持的宏处理语言(MPL)是一种字符串替换工具,使您能够编写可修复的代码块(宏)并将其插入源文本中的一个或多个位置。

宏处理器查看源文件的方式与汇编程序不同。

  • 对于汇编程序来说,源文件是一系列指令、语句和MCU指令。
  • 对于宏处理器,源文件是一长串经过处理的字符。宏处理器扫描源文件以搜索对已定义宏的调用。宏调用将替换为内置或用户定义的宏。

MPL 的一个有价值的功能是条件组装。在宏中使用条件汇编会导致紧凑的配置相关代码,这对于良好的程序设计至关重要。此外,它还生成尽可能紧凑的代码。

注意:

  • 宏处理在组装代码之前进行。它独立于程序集。宏时间不同于装配时间。因此,汇编程序知道的东西(如汇编语言符号、语言标签、使用 SET 和
    EQU 语句定义的符号以及位置计数器)对于宏处理器来说是未知的。

MPL 宏概述

在汇编程序中使用 MPL 宏相对容易。

  1. 使用MPL用于启用 MPL 宏处理器的汇编程序指令。更重要的是,使某些MPL宏扩展不会被禁用诺宏命令。
  2. 定义要使用的宏。您可以创建一个包含文件,其中包含要在源文件之间共享的宏定义。
  3. 调用或调用程序源中定义的宏函数。宏处理器扩展汇编程序组装的宏函数(在宏处理时)。

所有 MPL 预定义和用户定义的函数都必须以元字符开头。默认情况下,元字符是百分比 (‘%’) 字符。但是,元字符可能会被元炭MPL 函数。

MPL 元字符

所有 MPL 预定义和用户定义的函数都必须以元字符开头。默认情况下,元字符是百分号 (‘%’)。但是,元字符可能会被元炭MPL 函数。

定义 MPL 宏

定义 MPL 函数创建一个宏。定义函数的语法为:

%DEFINE (macro-name <[>parameter-list<]>) (macro-body)%*DEFINE (macro-name <[>parameter-list<]>) (macro-body)
%是元字符用于指示宏函数
*指定在文本模式下展开宏。
macro-name是宏的名称。宏名称最多可以包含 31 个字符,并且必须以 A-Z、a-z、_ 或 ?。后续字符可以是 A-Z、A-Z、_、?,或 0-9。
parameter-list是括在分隔符内并用分隔符分隔的参数列表。
macro-body是展开以替换宏名称和参数列表的文本。它可能包含对其他宏的调用。如果是这样,这些宏也会展开。定义宏时,在调用宏之前,宏主体中包含的那些宏调用不会展开。

注意:

  • 创建宏后,可以通过后续的 DEFINE 函数重新定义它。
  • 宏可以定义,也可以不带正式参数列表。
  • 参数列表是一个相当自由格式的列表。指定时要小心。

不带参数的宏

没有参数(或参数)的宏定义如下:

%*DEFINE (macro-name) (macro-body)

该定义需要宏名称和在调用宏时展开的宏主体。例如,以下宏定义:

%*DEFINE (my_asdf) (asdf)

当调用时:

%my_asdf

扩展到:

asdf

带参数的宏

具有参数(或参数)的宏定义如下:

%*DEFINE (macro-name <[>parameter-list<]>) (macro-body)

参数列表列出了传递给宏的形式参数。参数列表中的参数在宏主体中用于在调用宏时填充值。这允许您设计为许多操作生成代码的泛型宏。

参数列表中的参数由唯一标识符(您选择的)指定,这些标识符由宏分隔符(通常是括号和逗号)分隔。参数列表括在括号内,各个参数用逗号分隔。这只是一个约定,而不是一个要求。

参数列表规范的唯一要求是宏参数的传递方式和定义宏时使用的分隔符相同。例如,以下宏定义中的参数列表:

%*DEFINE (BMOVE (src, dst, cnt)) (...)

是(src,dst,cnt)。若要调用此宏,必须使用相同的分隔符指定参数。例如:

%BMOVE (1, 2, 3)

但是,没有理由必须将参数括在括号内或必须用逗号分隔。例如:

%*DEFINE (BMOVE src dst cnt) (...)

若要调用此宏,必须按如下方式指定参数:

%BMOVE 1 2 3

宏主体中的参数用参数名称表示,前面是元字符(在上面的示例中为 %src、%dst 和 %cnt)。以下宏定义显示了一个更完整的示例

%*DEFINE (BMOVE (src, dst, cnt)) LOCAL lab (MOV     R2,#%cntMOV     R1,#%srcMOV     R0,#%dst
%lab:   MOV     A,@R1MOV     @R0,AINC     R0INC     R1DJNZ    R2,lab
)

参数可以在宏主体中以任意次数和任意顺序使用。如果参数与宏同名并在宏正文中使用,则会展开该参数(而不是调用宏)。

如果宏与其中一个参数同名,则无法在宏主体中调用该宏,因为这会导致无限递归。

调用 MPL 宏

下面定义了一个名为 BMOVE 的宏,该宏采用三个参数:源、目标和计数。宏生成的代码将任意数量的字节从内存的一部分复制到另一部分。

%*DEFINE (BMOVE (src, dst, cnt)) LOCAL lab (MOV     R2,#%cntMOV     R1,#%srcMOV     R0,#%dst
%lab:   MOV     A,@R1MOV     @R0,AINC     R0INC     R1DJNZ    R2,lab
)

若要调用此宏,请指定元字符后跟宏名称和参数列表(如果有)。实际参数必须具有平衡的文本,并且可以包含对其他宏的调用。例如,可以按如下方式调用上述宏:

%BMOVE (array1,array2,10)

宏扩展为:

          MOV      R2,#10MOV      R1,#array1MOV      R0,#array2
??LAB?0:  MOV      A,@R1MOV      @R0,AINC      R0INC      R1DJNZ     R2,??LAB?0

注意:

  • 上面的示例会产生程序集错误,因为源文件不包含节定义。
  • 这GEN和GENONLY指令可用于在汇编程序列表文件中包括宏定义和宏调用。

局部符号

MPL 宏可能包括作为分支目标的本地标签。固定的标签名称会导致错误,如果多次调用宏。发生这种情况是因为同一标签名称在源文件中只能使用一次。此问题可以通过使用局部符号来解决。本地宏符号附加一个唯一的序列号,每次调用宏时,该数字都会递增。

必须在宏定义行中声明本地符号:

%*DEFINE (macro-name <[>parameter-list<]>) <[>LOCAL local-list<]> (macro-body)

其中,本地列表是宏的本地符号的列表(用逗号或空格分隔)。

局部符号在宏宏体中使用时必须以元字符为前缀。例如:

%*DEFINE (BMOVE (src, dst, cnt)) LOCAL lab (MOV     R2,#%cntMOV     R1,#%srcMOV     R0,#%dst
%lab:   MOV     A,@R1MOV     @R0,AINC     R0INC     R1DJNZ    R2,lab
)

表达式

MPL 宏处理器将平衡文本字符串解释为数值表达式,当它们用于以下 MPL 函数的参数时:

  • EVAL
  • IF
  • REPEAT
  • SUBSTR
  • WHILE

数值表达式的处理方式如下:

  • 表达式的文本以计算宏函数参数的普通方式展开。
  • 生成的字符串被计算为一个数值,该数值被转换为表达式值(表达式的最终值)的字符表示形式。数值表达式中可以使用以下运算符:
  • Parentheses()
  • HIGH,LOW
  • *, /, MOD, SHL, SHR
  • EQ, LT, LE, GT, GE, NE
  • NOT
  • AND,OR,XOR

MPL 数值表达式的算术是使用有符号 16 位整数执行的。关系运算符的结果为 0 (FALSE) 或 1 (TRUE)。

数值常量

可以使用下表中指定的后缀和字符以十六进制(以 16 为基数)、十进制(以 10 为基数)、八进制(以 8 为基数)和二进制(以 2 为基数)指定数字:

字符常量

MPL 宏处理器支持 ASCII 字符串,这些字符串可能包含一个或两个用单引号 (“'”) 括起来的字符。例如:
注意:
宏处理器无法访问汇编程序的符号表。因此,在宏处理过程中,标签以及 SET 和 EQU 符号的值是未知的。但是,您可以使用设置宏函数来定义宏符号。

相关文章:

基于Keil a51汇编 —— MPL 宏定义

MPL 宏 Ax51汇编程序支持的宏处理语言&#xff08;MPL&#xff09;是一种字符串替换工具&#xff0c;使您能够编写可修复的代码块&#xff08;宏&#xff09;并将其插入源文本中的一个或多个位置。 宏处理器查看源文件的方式与汇编程序不同。 对于汇编程序来说&#xff0c;源…...

Android 13 骁龙相机点击拍照流程分析(二)——点击拍照到存入相册

一.前言 本篇是在Android 13 骁龙相机点击拍照流程分析(一)——点击拍照到更新到左下角缩略图文章的基础上进行延申的,前面的预览、点击拍照的过程参考第一篇:Android 13 骁龙相机点击拍照流程分析(一)——点击拍照到更新到左下角缩略图-CSDN博客 二.生成图片并保存 从第…...

常见算法-巴斯卡三角形(Pascal)

常见算法-巴斯卡三角形&#xff08;Pascal&#xff09; 1、说明 巴斯卡&#xff08;Pascal&#xff09;三角形基本上就是在解 nCr&#xff0c;因为三角形上的每一个数字各对应一个nCr&#xff0c;其中 n 为 row&#xff0c;而 r 为 column&#xff0c;如下&#xff1a; 0C0 1…...

AI:09-基于深度学习的图像场景分类

图像场景分类是计算机视觉领域的重要任务之一,它涉及将图像分为不同的场景类别,如城市街景、山脉风景、海滩等。本文将介绍基于深度学习的图像场景分类方法,并提供相应的代码实例,展示了深度学习在图像场景分类中的技术深度和应用前景。 图像场景分类是计算机视觉中的一项…...

uni-app:引入echarts(使用renderjs)

效果 代码 <template><view click"echarts.onClick" :prop"option" :change:prop"echarts.updateEcharts" id"echarts" class"echarts"></view> </template><script>export default {data()…...

使用wireshark解析ipsec esp包

Ipsec esp包就是ipsec通过ike协议协商好后建立的通信隧道使用的加密包&#xff0c;该加密包里面就是用户的数据&#xff0c;比如通过的语音等。 那么如何将抓出来的esp包解析出来看呢&#xff1f; 获取相关的esp的key信息. 打开wireshark -> edit->preferences 找到pr…...

linux如何删除最近操作的日志

Linux系统下&#xff0c;不同的应用程序可能会生成不同的日志文件。如果你想要删除最近一段时间内的操作日志&#xff0c;可以使用一些命令来完成。 以下是一些常见的命令&#xff1a; dmesg&#xff1a;该命令用于显示内核环境下的运行信息和警告信息。如果你需要清空dmesg缓…...

android端MifareClassicTool

github地址 GitHub - ikarus23/MifareClassicTool: An Android NFC app for reading, writing, analyzing, etc. MIFARE Classic RFID tags. 开源项目 下载: https://www.icaria.de/mct/releases/ 功能 1、读取Mifare Classic卡片 2、编辑并保存卡片的数据 3、写入Mifare C…...

设计模式 - 迭代器模式

目录 一. 前言 二. 实现 三. 优缺点 一. 前言 迭代器模式是一种行为型设计模式&#xff0c;它提供了一种统一的方式来访问集合对象中的元素&#xff0c;而不暴露集合内部的表示方式。简单地说&#xff0c;就是将遍历集合的责任封装到一个单独的对象中&#xff0c;我们可以按…...

Docker之Dockerfile搭建lnmp

目录 一、搭建nginx ​编辑 二、搭建Mysql&#xff08;简略版&#xff09; 三、搭建PHP 五、补充 主机名ip地址主要软件mysql2192.168.11.22Docker 代码示例 systemctl stop firewalld systemctl disable firewalld setenforce 0docker network create --subnet172.18.…...

排序算法——选择排序

一、介绍&#xff1a; 选择排序就是按照一定的顺序从选取第一个元素索引开始&#xff0c;将其储存在一个变量值中&#xff0c;根据排序规则比较后边每一个元素与这个元素的大小&#xff0c;根据排序规则需要&#xff0c;变量值的索引值进行替换&#xff0c;一轮遍历之后&#x…...

【数据结构C/C++】双向链表的增删改查

文章目录 CC408考研各数据结构C/C代码&#xff08;Continually updating&#xff09; 对我个人而言&#xff0c;在开发过程中使用的比较多的就是双向链表了。 很多重要的代码优化都会使用到基于双向链表实现的数据机构。 比如我们常用的HashMap&#xff0c;我们知道Key其实是无…...

Godot 添加Nuget 引用

前言 我的Godot 专栏 我在之前的文章中&#xff0c;解决了Visual Studio 如何去调试正在运行的Godot 程序。Godot 对于C# 的支持只剩下一个&#xff0c;那就是Nuget 添加。 Godot VisualStudio外部编辑器设置 添加Nuget Nuget 添加还是非常的容易的。我们直接添加一个最常用的…...

IC工程师职场必备《经典Verilog100多个代码案例》(附下载)

对于IC行业的人员而言&#xff0c;Verilog是最基础的入门&#xff0c;用于数字电路的系统设计&#xff0c;很多的岗位都会用到&#xff0c;可对算法级、门级、开关级等多种抽象设计层次进行建模。 Verilog由于其简单的语法&#xff0c;和C语言的相似性&#xff0c;目前被各大公…...

springboot项目做成公共项目

一&#xff1a;引言 最近碰到个需求&#xff0c;就是把我项目做成一个公共的提供jar包给别人使用&#xff0c;我也是捣鼓了一段时间去研究这个问题&#xff0c;这个东西其实就是A 项目提供jar包给B项目&#xff0c;B项目只要引入A项目的jar包就可以使用A项目的功能。 问题一&…...

RTC 时间、闹钟

实时时钟RTC是一个独立的定时器。RTC模块拥有一个连续计数的计数器&#xff0c;在软件配置下&#xff0c;可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期 RTC还包含用于管理低功耗模式的自动唤醒单元。 在掉电情况下 RTC仍可以独立运行 只要芯片的备用电源…...

【yolo系列:yolov7训练添加spd-conv】

系列文章目录 yolov7训练添加spd-conv 文章目录 系列文章目录一、spd-conv是什么&#xff1f;二、使用步骤1.第一步&#xff1a;先在models/common.py加上2.第二步&#xff1a;models/yolo.py加上2.第三步&#xff1a;修改yolov7的yaml文件 总结 提示&#xff1a;以下是本篇文…...

面向对象设计-UML六种箭头含义

目录 UML概述UML语义UML表示法 六种常用关系标识方法泛化实现依赖关联聚合组合 本文参考文章 https://blog.csdn.net/qq_25091281/article/details/123801862 UML概述 UML (Unified Modeling Language)为面向对象软件设计提供统一的、标准的、可视化的建模语言。适用于描述以…...

一本没有任何数学公式的自然语言处理入门书

ChatGPT 时代来了&#xff0c;AI 从旧时王谢堂前燕&#xff0c;飞入寻常百姓家。越来越多非 AI 领域 的软件开发者涌进 NLP(自然语言处理)领域。在这个快速发展的时代&#xff0c;如果这些软件开发 者要像读书那样先读 4 年本科、2 年硕士、3 年博士才能搞 AI&#xff0c;风口早…...

【数据结构C/C++】多维数组的原理、访问方式以及作用

文章目录 什么是多维数组&#xff1f;代码讲解使用方式为什么指针遍历的方式是这样子的&#xff1f;&#xff08;助你理解指针的含义&#xff09;使用场景408考研各数据结构C/C代码&#xff08;Continually updating&#xff09; 什么是多维数组&#xff1f; 在C语言中&#x…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...