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

【ASMbits--常用算术运算指令】

ASMbits--常用算术运算指令

  • 1 基本运算算术指令--最基础
    • 1.1 加法和减法
    • 1.2 移位操作
    • 1.3 乘法
  • 2 practice
    • 2.1 编写invert(int n)
    • 2.2 编写judge_odd(int n)
    • 2.3 计算绝对值abs(int n)
    • 2.4 add(int n1, int n2)函数
    • 2.4 shift寄存器
    • 2.5 sihft ath right
    • 2.6 shift left

在ARMv7汇编中,代码片段:

1: b 1b	//Done

作用是创建一个无限循环,使程序永远停留在当前位置,不在执行后续命令;

语法解释:

  • 1::这是一个局部标签(local label)。在 ARM 汇编中,以数字开头的标签(如 1:)是局部标签,可以通过 b 1b 或 b 1f 引用。
    1b:表示向后查找最近的 1: 标签(Backward)。
    1f:表示向前查找最近的 1: 标签(Forward)。

  • b 1b:这是一个分支指令(Branch),跳转到最近的 1: 标签(向后查找)。由于标签 1: 就在当前行,这条指令会无限循环跳转到自身。

代码 1: b 1b 的作用是让程序在当前位置无限循环,防止后续未定义代码的执行。这是裸机编程或嵌入式系统中常见的“安全终止”方法。
具体在裸机程序(无操作系统)或嵌入式系统中,这种无限循环常用于:

  • 防止程序执行到未定义的内存区域(例如代码结束后未初始化的内存)。
  • 保持程序在完成所有任务后“挂起”(例如在调试时观察结果);

1 基本运算算术指令–最基础

1.1 加法和减法

  • ADD 加法
    语法:ADD{条件}{S} 目标寄存器, 操作数1, 操作数2
    功能:将操作数1和操作数2相加,结果存入目标寄存器。
ADD R0, R1, R2     @ R0 = R1 + R2
ADD R3, R4, #10    @ R3 = R4 + 10
  • SUB减法
    语法:SUB{条件}{S} 目标寄存器, 操作数1, 操作数2
    功能:从操作数1中减去操作数2,结果存入目标寄存器。
SUB R0, R1, R2     @ R0 = R1 - R2
SUB R3, R4, #5      @ R3 = R4 - 5

1.2 移位操作

  • LSL逻辑左移
    语法:LSL{条件}{S} 目标寄存器, 操作数, 移位位数
    功能:将操作数左移指定位数,低位补零。
LSL R0, R1, #4      @ R0 = R1 << 4
  • LSR逻辑右移
    语法:LSR{条件}{S} 目标寄存器, 操作数, 移位位数
    功能:将操作数右移指定位数,高位补零。
LSR R0, R1, #3      @ R0 = R1 >> 3(无符号)
  • ASR(算术右移)
    语法:ASR{条件}{S} 目标寄存器, 操作数, 移位位数
    功能:将操作数右移指定位数,高位补符号位(用于有符号数)
ASR R0, R1, #2      @ R0 = R1 >> 2(保留符号)
  • ROR循环右移
    语法:ROR{条件}{S} 目标寄存器, 操作数, 移位位数
    功能:将操作数循环右移指定位数,移出的位补到高位。
ROR R0, R1, #8      @ R0 = R1 循环右移8位

1.3 乘法

  • MUL无符号乘法
    语法:MUL{条件}{S} 目标寄存器, 操作数1, 操作数2
    功能:操作数1 × 操作数2,结果低32位存入目标寄存器。
MUL R0, R1, R2     @ R0 = (R1 × R2) 的低32位
  • MIL乘加
    语法:MLA{条件}{S} 目标寄存器, 操作数1, 操作数2, 操作数3
    功能:操作数1 × 操作数2 + 操作数3。
MLA R0, R1, R2, R3  @ R0 = (R1 × R2) + R3

2 practice

2.1 编写invert(int n)

Write a function that returns the bitwise inversion of its parameter.
int invert (int n);

.global _start
_start:
    mov r0, #1
    bl invert
    1: b 1b    // Done

.global invert
invert:
    MVN r0,r0  // MVN把R0里面的数取反然后再进行存储
    BX lr	//return caller

2.2 编写judge_odd(int n)

算法:最低位是0还是1,若是1则odd为1,若是为0,则odd为0;如何获得最低位呢,直接使用n & 1;
Steps:

  1. 将r0与1进行AND操作,结果存在某个寄存器,比如r0本身。
  2. 然后比较这个结果是否为0,如果不为0,则返回1,否则返回0。
.global _start
_start:
    mov r0, #1
    bl odd
    1: b 1b    // Done

.global odd
odd:
	AND r0,r0,#1
    BX lr
	

2.3 计算绝对值abs(int n)

算法:进制补码中,负数的符号位是1,正数或零是0。所以,如果我能得到符号位的掩码,可能可以用异或和减法来计算绝对值。比如,对于n,如果符号位是0,那么绝对值是n本身;如果符号位是1,绝对值是~n + 1。或者用另一种方法:将n与符号位的掩码异或,然后减去掩码。这可能更高效。
步骤:

  1. 将n算术右移31位,得到mask(0或-1)。
  2. 异或n和mask,得到n ^ mask。
  3. 减去mask,即(n ^ mask) - mask。因为mask是0或-1,当mask是-1时,减法相当于加1。
.global _start
_start:
    mov r0, #10
    bl abs
    1: b 1b    // Done

.global abs
abs:
    ASR r1, r0, #31	// r1 = n>>31 to generate mask
    EOR r0, r0, r1		// r0 = n ^ mask
    SUB r0, r0, r1		// r0 = r0 - mask
    BX lr
	

2.4 add(int n1, int n2)函数

即第一个参数传递给R0,第二个参数传递给R1;

.global _start
_start:
    mov r0, #1  // First function parameter is always passed through r0.
    mov r1, #1  // Second function parameter is always passed through r1.
    bl add      // Return value is always in r0.
    1: b 1b     // Done

.global add
add:
    ADD R0,R0,R1
    BX LR
	

2.4 shift寄存器

即将该参数移位到24位,低8位;

.global _start
_start:
    ldr r0, =0x12345678
    bl shift
    b _start        // End of testing code

// Convert one U32 sample to U8 format
shift:
    LSR r0,r0,#24	//将输入参数 r0 右移24位,保留高8位到低8位
    BX lr

2.5 sihft ath right

// A test case to test your function with

.global _start
_start:
    ldr r0, =0x40000
    bl shift
    b _start        // End of testing code

// Return 1/4 amplitude for a S32 sample
shift:
	ASR r0,r0,#2	//算数右移
    BX lr

2.6 shift left

// A test case to test your function with

.global _start
_start:
    ldr r0, =0x1234
    bl shift
    b _start        // End of testing code

// Convert one S16 to S32 format
shift:
	LSL R0,R0,#16	// left shift 16
    BX lr

以上是ARMv7汇编语言的常见算术指令运算;

相关文章:

  • 《从零手写Linux Shell:详解进程控制、环境变量与内建命令实现 --- 持续更新》
  • 掌握Windows命令提示符中的万能符:*号的全方位使用指南
  • 2.2[frontEnd]ESLint
  • 语音识别 FireRedASR-AED模型主要特点
  • Gitee重新远程连接仓库(Linux)
  • Spring boot+mybatis的批量删除
  • 模运算的艺术:从基础到高阶的算法竞赛应用
  • AI大白话(一):5分钟了解AI到底是什么?
  • 知识图谱流程说明
  • 开源通义万相本地部署方案,文生视频、图生视频、视频生成大模型,支持消费级显卡!
  • DAY34 贪心算法Ⅲ
  • MinIo前后端实现
  • 深度解析React Native底层核心架构
  • Axure高级功能深度解析一一高效原型设计的利器
  • overcommit_never 和overcommit_guess 的定义和使用
  • APP自动化测试-备忘录:Appium 2.X的安装和启动服务方法
  • 【C语言】动态内存分配函数calloc
  • 设计模式-策略模式
  • 网络运维学习笔记(DeepSeek优化版) 017 HCIA-Datacom综合实验02
  • 【前沿 热点 顶会】CVPR 2025 录用的基于扩散模型的图像生成方向的论文
  • 深入贯彻中央八项规定精神学习教育中央指导组派驻地方和单位名单公布
  • 西藏阿里地区日土县连发两次地震,分别为4.8级和3.8级
  • 跟着京剧电影游运河,京杭大运河沿线六城举行京剧电影展映
  • 外交部:美方应在平等、尊重和互惠的基础上同中方开展对话
  • 商务部新闻发言人就波音公司飞回拟交付飞机答记者问
  • 专访|首夺天元头衔创生涯历史,王星昊打算一步一步慢慢来