ARM 算数指令

加法	ADD
减法	SUB
取负	NEG
比较	CMP
乘法	MUL
移位	LSL、LSR、ASL、ASR、ROL、ROR

加法和减法

绝大多数微处理器都实现了带进位的加法指令,能够将两个操作数和条件码寄存器中的进位位加到一起。这条指令会使字长大于计算机固有字长的链接运算更加方便。
说明了如何使用带进位的加法指令实现链式运算。如:指令ADD r2,r1,r0将源寄存器r0和r1的内容相加,将结果保存到r2中,该操作产生的进位被保存到进位位中。
在这里插入图片描述
假设使用32位体系结构的ARM处理器,要处理64位整数并要完成64位加法。上图(b)说明了64位算术运算中如何使用32位寄存器来传播进位。两个64位数已经保存到寄存器r1、r0和r3、r2中。
指令ADDS r4,r0,r2,完成r0+r2并将结果保存到r4中,进位输出保存到CCR中进位位中。
指令ADC r5,r1,r3将高位的两个数字相加时,进位位也被加到r1与r3的和中。助记符ADC表示带进位的加法。

ARM还提供了SBC或带借位的减法指令来支持扩展精度的减法运算。

逆减法指令RSB:减法指令SUB r1,r2,r3被定义为[r1]<-[r2] – [r3],逆减法指令RSB r1,r2,r3被定义为[r1]<-[r3]-[r2]

取负

取负就是用零减去一个数字。如r0的负数就是0 - [r0]。ARM没有这样的取负指令。可以使用逆减法来实现,因为RSB r1,r1,#0等价于NEG r1

比较

通过执行指令CMP Q,P比较P和Q时,将发生显示比较,这条指令会计算Q-P但
不会保存结果。比较操作会修改CCR的内容,后面的指令会测试CCR的值以决定
按顺序继续执行还是进行跳转。

考虑下面的例子:
CMP r1,r2 ; r1=r2?
BEQ DoThis ; 如果相等则跳转到DoThis
ADD r1,r1,#1 ; 否则r1 = r1 + 1
B Next ; 不要忘记跳过THEN部分代码
.
DoThis SUB r1,r1,#1 ; r1 = r1 -1
Next … ; 两个分叉汇聚于此

乘法

乘法运算将两个m位的操作数相乘,得到一个2m位 的积。结果的位长加倍带
来一个问题。计算机要么自动将结果截断,32位乘以32位得到一个32位结果。
要么设计一个四操作数指令:两个源操作数,两个目的操作数(分别保存结果
的高半部分和低半部分)。而且,二进制补码加减法运算能得到正确结果,但
乘除法却不一定,即对有符号和无符号数不能使用同样的乘法操作。

有些微处理器提供了有符号和无符号乘法操作,以及结果为32位的16位乘法、
结果为64位的32位乘法。

ARM乘法指令MUL Rd,Rm,Rs计算保存在32位寄存器Rm和Rs中的两个32位有符号数的积,将结果保存在32位寄存器Rd中,仅存放64位积的低32位。当然,应保证结果不超出范围。如,计算121乘96:
MOV r0,#121 ; 将121加载到r0中
MOV r1,#96 ; 将96加载到r1中
MUL r2,r0,r1 ; r2 = r0 x r1

目的寄存器Rd和源寄存器Rm不用使用相同的寄存器,因为ARM在乘法计算过程中将Rd当作临时寄存器使用,这是Arm的一个特点。

除了32位乘法指令MUL外,ARM还包括:

UMULL 无符号长整型乘法(Rm x Rd乘积为64位,存放在两个寄存器中)
UMLAL 无符号长整型乘累加
SMULL 有符号长整型乘法
SMLAL 有符号长整型乘累加

MLA

ARM乘累加指令MLA,先进行乘法,再将乘积与另一个数相加。
MLA指令采用四操作数形式:MLA Rd,Rm,Rs,Rn。RTL定义为[Rd]<-[Rm]x[Rs]+[Rn],32位数与32位数的乘积被截断为低32位结果。

内积运算

ARM乘累加操作使用一条指令完成乘法和加法运算,支持内积计算。
假设向量a有n个元素a1,a2,…,an,向量b有n个元素b1,b2,…,bn,则a与b的内积就是标量s=a x b = a1 x b1 + a2 x b2 +…+ an x bn
下面代码段展示MAL指令计算两个n元素向量Vector1和Vector2的内积:
n EQU 4
MOV r4,#n ; r4为循环计数器
MOV r3,#0 ; 将内积清零
ADR r5,Vector1 ; r5指向Vector1
ADR r6,Vector2 ; r6指向Vector2

	Loop	LDR	r0,[r5],#4	; REPEAT 读向量Vector1的一个元素并更新指针LDR	r1,[r6],#4	;	读取向量Vector2的相应元素MLA	r3,r0,r1,r3	;	乘累加操作r3= r3 + r0 x r1SUBS	r4,r4,#1		;	循环计数器递减(更新CCR)BNE	Loop		; UNTIL所有计算完毕

位操作

逻辑操作也叫位操作,这些操作被应用到寄存器的每一位。微处理器一般只支持AND(与)、OR(或)、NOT(非)和EOR或(异或)操作。

下面说明了对r1=110010102和 r0=000011112进行的逻辑操作:
在这里插入图片描述
逻辑运算的典型应用就是数据合并,即把多个变量合并到一个寄存器或存储单元中。

假设寄存器r0包含8位数bbbbbbxx,寄存器r1包含8位数bbbyyybb,寄存器r2包、
含8位数zzzbbbbb,x、y、z代表需要的位,b是不需要的位。希望把这些位合并
得到最后结果zzzyyyxx。通过以下代码可以到达目的:
AND r0,r0,#2_00000011 ; 保留2位xx,其他屏蔽
AND r1,r1,#2_00011100 ; 保留3位yyy,其他屏蔽
AND r2,r2,#2_11100000 ; 保留3位zzz,其他屏蔽
OR r0,r0,r1 ; 合并r1和r0得到000yyyxx
OR r0,r0,r2 ; 合并r2和r0得到zzzyyyxx

假设有一个8位二进制串abcdefgh,需要b、d两位清零,a、e、f三位置1,h位
取反。可以通过AND、OR和EOR操作完成:

AND	r0,r0,#2_10101111		; 清除b和d位,得到a0c0efgh
OR	r0,r0,#2_10001100		; a、e、f位置1,得到10c011gh
EOR	r0,r0,#2_00000001		; b位取反,得到10c011gh(h取反)

位清楚指令BIC

ARM提供了位清除指令BIC,将第一个操作数与第二个操作数的反码进行与操作。如,IBC r0,r1,r2实现了:

如果BIC第二个操作数中某位为0,则将第一个操作数中对应的位复制到目的操作数中,如果第二个操作数中某位为1,则把目的操作数中对应的位清零。

如果r1=10101010且r2=00001111,则BIC r0,r1,r2的结果为:
在这里插入图片描述

可用BIC指令对寄存器的最低位字节清零。指令BIC r0,r1,#0xFF把寄存器r1中的32位复制到寄存器r0中,然后把r0中的第0~7位清零。

移位操作

移位操作就是把字中的位向左或向右移动一个或多个位置。当移位一个位串时,串的一端的位会被丢弃,并在另外一端补充新的位,如:

在这里插入图片描述
这里的移位是逻辑移位

在这里插入图片描述
所有微处理器都支持逻辑移位操作。有些支持向左或向右移动一位,其他的支持多位移位。如
果移位的位数在指令中被编码为常量,这种移位叫作静态移位,在运行时不能改变移位位数,
如果移位的位数由寄存器的值指定,则叫作动态移位,可以在程序运行时修改移位的位数。

移位的典型应用是从一个字中提取特定的位。假设有一个8位的串bxxxxbbb,x表示要提取的位,
b表示无需关心的位。下面代码提取所需要的位且将其右对齐:
LSR r0,r0,#3 ; r0右移3位,得到000bxxxx
AND r0,r0,#2_00001111 ; 屏蔽不需要的位,得到0000xxxx

ARM没有独立的移位指令,移位是作为其他指令的一部分来实现的。ARM允许对寄存器-寄存
器型指令的第二个操作数进行移位。如,指令ADD r0,r1,r2,LSL #4,先寄存器r2逻辑左移4位,
然后将移位结果与寄存器r1相加。

算术移位

算术移位将操作数视作一个有符号二进制补码。可以用来完成除以2(右移一
位)或乘以2(左移一位)等运算。算术移位的目的是在进行移
位运算时保留二进制补码数的符号,移位运算代表乘以或除以2的幂。
算术左移与逻辑左移是等价的。算术右移会保留符号位,每次右移后符号位会
自动复制。

例如,如果将8位数11001110算术左移一位,得到10011100(最低位补0),而
算术右移一位得到11100111(符号位被复制)。一个整数算术左移m位相当于
乘以2m,而算术右移m位相当于除以2m。

循环移位

循环移位操作把寄存器的内容看作一个LSB(最低位)和MSB(最高位)相邻的环。如上图
(c),进行移位操作时,从一端移出的位会从另一端进来。与逻辑移位和算术移位相比,循
环移位不会丢失位。
例如,如果将8位数11001110循环左移一位,得到10011101,移出的位也被复制到进位寄存器。

有些处理器实现了另一种循环操作,叫作扩展循环移位或带进位的循环移位。这种操作与循环
移位一样,只不过循环时包含了进位位。
如下图,移出的位被复制到进位位,原来的进位位变成了被移出的位:
在这里插入图片描述

ARM移位操作的实现

ARM没有独立的移位操作。实际上,移位操作与其他数据处理操作组合到一起,可以在使用第
二个操作数之前将其移位。
下图描述了ARM的移位机制,在第二个源操作数的数据通路上增加了一个桶形移位器:
在这里插入图片描述
考虑第二个源操作数被移位的ADD操作的例子:
在这里插入图片描述
将r2与r1相加之前,先将r2的内容逻辑左移一位,因此该操作等价于
在这里插入图片描述
如果仅希望对寄存器进行移位操作,而不需要进行其他数据处理,可以使用下面指令:
MOV r3,r3, LSL #1

由于可以完成动态移位,也可使用指令MOV r4,r3,LSL r1,以r1为移位位数对r3
进行移位,结果送入r4。

假设r0中的数为0.00000010101111….,希望规格化为0.101…,如果用寄存器r1
表示指数,则执行MOV r0,r0,LSL r1可以在一个周期内完成规格化操作。

除了仅允许移动一位RRX指令外,ARM支持静态和动态移位。静态移位在编程
时就已经确定了移位的位数,而动态移位允许在执行代码时改变移位位数。如,
指令MOV r3,r3,LSL r2以r2的值为移位位数对r3进行逻辑左移。r2的值被看作模
32的数,因为移位不能超过32次。

ARM仅实现了以下5种移位操作
LSL 逻辑左移
LSR 逻辑右移
ASR 算术右移
ROR 循环右移
RRX 带进位的循环右移(移位一次)

尽管没有循环左移操作,可以借助循环右移实现。
下面说了4位二进制数的循环左移和循环右移。经过4次循环移位,操作数没有
变化。循环左移和循环右移是对称的。对于32位数,循环左移n位等价于循环
右移32-n位。
循环右移 循环左移
1101 开始 1101 开始
1110 循环右移1次 1011 循环左移1次
0111 循环右移2次 0111 循环左移2次
1011 循环右移3次 1110 循环左移3次
1101 循环右移4次 1101 循环左移4次
ARM没有实现带进位的循环左移操作,通过指令ADCS r0,r0,r0可以实现带进位
的循环左移,因为它把r0与r0以及进位位一起相加,并将结果保存在r0中(即
结果为2 x [r0] + C),左移等价于乘以2,把进位位移动到最低位等价于加上进
位位,得到2 x [r0] + C,指令后添加S会强制更新CCR,确保进位输出被加载到C
位。因此ADCS r0,r0,r0与RXL r0等价。

指令编码——洞察ARM体系结构

简单的看一下ARM的移位操作是如何编码的,下图给出了ARM数据处理指令的二进制编码,遵循RISC体系结构 的一般模式:包括一个操作数、两个寄存器操作数以及第三个多目的操作数。寄存器操作数r源和r目的定义了第一个源操作数和目的寄存器。0~11位是第二个源操作数的编码:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/79565.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA---集合ArrayList

集合 1. 自动扩容 &#xff0c;集合长度可变 2. 只可以存引用数据类型&#xff0c;如果要存基本数据类型&#xff0c;需要将其转换成对应的包装类 ArrayList 定义在 java.util 下的&#xff0c;实现了 List 接口。ArrayList 内部以动态数组的形式存储元素&#xff0c;这意…

Scrapy框架之【settings.py文件】详解

settings.py 文件的主要作用是对 Scrapy 项目的全局设置进行集中管理。借助修改这个文件中的配置项&#xff0c;你可以对爬虫的行为、性能、数据处理等方面进行灵活调整&#xff0c;而无需修改爬虫代码。 ①默认英文注释settings.py # Scrapy settings for douban project # …

Java变量学习笔记

Java变量 -为什么需要变量&#xff1f; 一个程序就是一个世界 变量是程序的基本组成单位 不论是使用哪种高级程序语言编写程序,变量都是其程序的基本组成单位&#xff0c;比如: //变量有三个基本要素(类型名称值) class Test{public static void main(String [largs){int a1;…

数据结构*队列

队列 什么是队列 是一种线性的数据结构&#xff0c;和栈不同&#xff0c;队列遵循“先进先出”的原则。如下图所示&#xff1a; 在集合框架中我们可以看到LinkedList类继承了Queue类&#xff08;队列&#xff09;。 普通队列&#xff08;Queue&#xff09; Queue中的方法 …

Nginx — 防盗链配置

防盗链简述 防盗链是一种保护网络资源所有者权益的技术手段&#xff0c;旨在防止未经授权的用户或网站通过直接链接的方式盗用资源&#xff0c;以下是关于防盗链的简述&#xff1a; 原理 基于请求头验证&#xff1a;服务器通过检查请求头中的特定字段&#xff0c;如Referer字…

【浅学】Windows下ffmpeg+nginx+flv将本地视频推流在本地搭建的Web前端页面中播放,超详细步骤

Nginx安装和配置 下载nginx-1.19.3-http-flv 模块预编译包并解压放在d盘&#xff0c;路径就跟安装步骤里说的一样(如下图)&#xff0c;不然会有其他问题出现。 打开conf/nginx.conf&#xff0c;查看RTMP和http相关的配置&#xff0c;确认端口号和路由名称 ffpemg推流视频…

Ubuntu-tomcat安装部署

https://blog.csdn.net/weixin_43877427/article/details/144697087 Linux下Tomcat安装与配置_tomcat linux安装及配置教程-CSDN博客 一、下载Tomcat 1、官网下载 进入后根据自己需要选择不同的版本&#xff0c;点击download 进入后&#xff0c;在下图标注的里边选择要下载…

希洛激活器策略思路

在复杂多变的外汇市场中&#xff0c;交易者常常寻求有效的工具来辅助决策。 希洛激活器作为一种综合性的技术指标&#xff0c;结合了江恩理论、CCI&#xff08;商品通道指数&#xff09;和MACD&#xff08;移动平均收敛发散指标&#xff09;&#xff0c;旨在为交易者提供更为全…

n8n工作流自动化平台的实操:本地化高级部署

一、本地高级部署 1.下载 docker pull docker.n8n.io/n8nio/n8n 2.运行 docker volume create n8n_data docker run -dit --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n -e N8N_SECURE_COOKIEfalse -e N8N_RUNNERS_ENABLEDtrue -e N8N_ENFORCE_SETTINGS_FIL…

vector和string的迭代器

1. 迭代器的本质 (1) 标准要求 C 标准要求 std::string 和 std::vector 的迭代器必须是 随机访问迭代器&#xff08;Random Access Iterator&#xff09;。 指针天然满足随机访问迭代器的所有操作&#xff08;如 、--、n、* 等&#xff09;&#xff0c;因此可以直接用指针实现…

PyCharm代理配置全攻略:系统设置+Python运行环境一键搞定

文章目录 1. 设置系统代理1.1 作用范围1.2 使用场景1.3 设置步骤 2. 设置 python 运行/调试代理2.1 作用范围2.2 使用场景2.3 设置步骤 Pycharm 工具作为一款强大的 IDE&#xff0c;其代理配置在实际开发中也是必不可少的&#xff0c;下面介绍下如何配置 Pycharm 的代理。 1. …

stm32 g031g8 flash擦除函数被坑

先记录一下在擦除的时候由于调用了这个FLASH_PageErase(FLASH_BANK_1, secpos); 导致擦除不成功&#xff0c;写入失败。 下面的擦除有问题// 使用 FLASH_PageErase 擦除该页while ((FLASH->SR & FLASH_SR_BSY1) ! 0); // 等待空闲FLASH_PageErase(FLASH_BANK_1, secpo…

深度学习与 PyTorch 基础

笔记 1 深度学习简介 1.1 深度学习概念 深度学习是机器学习的一类算法, 以人工神经网络为结构, 可以实现自动提取特征 深度学习核心思想是人工神经网络为结构, 自动提取特征 1.2 深度学习特点 自动提取特征 解释性差 大量数据和高性能计算能力 非线性转换(引入非线性因…

【Unity】XLua访问C#文件

创建NPC.cs&#xff1a; public class NPC { public string name; public int age; public void Say() { Debug.Log("Say:我是未被修改的"); } public static void Say() { Debug.Log("Static Say:我是未被修改的"); } public void Say2(int a) { Debug.Lo…

【第十六届蓝桥杯省赛】比赛心得与经验分享(PythonA 组)

文章目录 一、我的成绩二、我的备赛经历三、如何备赛&#xff08;个人观点&#xff09;1. 基础语法2. 数据结构3. 算法4. 数学 四、做题技巧与注意事项五、我的题解试题A 偏蓝 &#x1f3c6;100%试题B IPV6 &#x1f3c6;0%试题C 2025图形 &#x1f3c6;100%试题D 最大数字 &am…

基于Springboot+Mysql的校园博客系统(含LW+PPT+源码+系统演示视频+安装说明)

系统功能 管理员功能&#xff1a;首页、个人中心、博主管理、文章分类管理、文章信息管理、举报投诉管理、系统管理&#xff1b;博主功能&#xff1a;首页、个人中心、文章信息管理、举报投诉管理、我的收藏管理&#xff1b;前台首页功能&#xff1a;首页、文章信息、系统公告…

第三次作业(密码学)

#include <stdio.h> #include <stdlib.h> // 计算最大公约数 int gcd(int a, int b) { while (b ! 0) { int temp b; b a % b; a temp; } return a; } // 计算模幂运算 int mod_pow(int base, int exponent, int modulus) { …

3.0/Q1,Charls最新文章解读

文章题目&#xff1a;Association between outdoor artificial light at night and metabolic diseases in middle-aged to older adults-the CHARLS survey DOI&#xff1a;10.3389/fpubh.2025.1515597 中文标题&#xff1a;夜间户外人工光与中老年人代谢性疾病的关联-CHARLS调…

MATLAB 中zerophase函数——零相位响应

零相位响应&#xff08;Zero-Phase Response&#xff09;是指滤波器的幅度函数&#xff0c;但相位为零。滤波器的相位响应为零&#xff0c;意味着不同频率的信号通过滤波器后&#xff0c;其相位不发生任何变化&#xff0c;即信号的波形在时间轴上没有偏移。 零相位响应指的是当…

马克思最基本的哲学思想--改造世界以实现人的自由全面发展--deepseek

马克思的哲学思想可以概括为“改造世界以实现人的自由全面发展”&#xff0c;这句话看似简单&#xff0c;却包含了其哲学的核心逻辑。我们可以从三个层面展开分析&#xff1a; 1. “改造世界”——实践是哲学的终极使命 马克思在《关于费尔巴哈的提纲》中写道&#xff1a; “哲…