ARM 汇编指令:LSL(逻辑左移) 和 LSR(逻辑右移)

ARM 汇编指令:LSL(逻辑左移) 和 LSR(逻辑右移)

本文来自于我关于 ARM 汇编指令系列文章。欢迎阅读、点评与交流~
1、汇编指令在不同架构中的联系与区别
2、ARM 汇编指令:MOV
3、ARM 汇编指令:LDR
4、ARM 汇编指令:STR
5、ARM 汇编指令:MRS 和 MSR
6、ARM 汇编指令:ORRS
7、ARM 汇编指令:BEQ
8、ARM 汇编指令:TST
9、ARM 汇编指令:B
10、ARM 汇编指令:BX
11、ARM 汇编指令:ERET
12、ARM 汇编指令:STP\LDP
13、ARM 汇编指令:UBFX
14、ARM 汇编指令:STM
15、ARM 汇编指令:LDM
16、ARM 汇编指令:LSL(逻辑左移) 和 LSR(逻辑右移)
17、ARM 汇编指令:ROR(循环右移)

LSLLSR 是 ARM 汇编中两个最基础且重要的移位指令。

核心概念:移位操作

在了解具体指令前,首先要明白移位 是什么。想象一个二进制数,比如 8 的 8 位二进制表示是 00001000

  • 左移 就是将所有位向左移动,空出的低位补 0。00001000 左移 1 位变成 00010000(即 16)。左移一位通常相当于乘以 2
  • 逻辑右移 就是将所有位向右移动,空出的高位补 0。00001000 右移 1 位变成 00000100(即 4)。逻辑右移一位通常相当于除以 2(向零取整)

在 ARM 中,移位操作不仅可以单独使用,还能与大多数数据处理指令(如 ADD, MOV, CMP 等)免费结合 ,这是 ARM 指令集一个非常强大和灵活的特性。但我们先看作为独立指令的 LSLLSR


1. LSL - 逻辑左移

功能 :将寄存器中的二进制位向左移动指定的位数,右侧空出的低位用 0 填充。
本质:相当于无符号乘法(乘以 2^n)。

语法

armasm 复制代码
LSL{S} <Rd>, <Rm>, <Rs>        ; 用寄存器 Rs 的值指定移位位数
LSL{S} <Rd>, <Rm>, #<imm5>     ; 用立即数 imm5 (0-31) 指定移位位数
  • {S}:可选的条件标志更新后缀。如果加上 S,则根据移位结果更新 CPSR 中的 N(负标志)和 Z(零标志)。移位操作也会影响 C(进位标志)。
  • <Rd>:目标寄存器。
  • <Rm>:源操作数寄存器。
  • <Rs>:存放移位位数的寄存器(通常只使用低 8 位)。
  • #<imm5>:5 位立即数移位量(0-31)。

工作原理

复制代码
Before:  Rm = [b31 b30 ... b1 b0]
After:   Rd = [b31-n ... b0  0 ... 0]  <-- n 个 0 填入低位
                \___________/
                向左移动 n 位

最后移出的那一位(原 b31-n+1 位)会进入 CPSRC(进位)标志。

示例

armasm 复制代码
MOV     R1, #5          ; R1 = 5 (二进制 00000101)
LSL     R0, R1, #2      ; R0 = R1 << 2
; 计算过程: 00000101 << 2 = 00010100
; 结果: R0 = 20 (5 * 4)
armasm 复制代码
MOVS    R2, #0x80000001 ; R2 = 0x80000001,设置标志
LSLS    R3, R2, #1      ; R3 = R2 << 1,并更新标志
; 计算过程: 1000...0001 << 1 = 0000...0010
; 结果: R3 = 0x00000002
; 标志变化:最后移出的 '1' 进入 C 标志,所以 C = 1。结果非零,所以 Z = 0。

2. LSR - 逻辑右移

功能 :将寄存器中的二进制位向右移动指定的位数,左侧空出的高位用 0 填充。
本质:相当于无符号除法(除以 2^n)。

语法

armasm 复制代码
LSR{S} <Rd>, <Rm>, <Rs>        ; 用寄存器 Rs 的值指定移位位数
LSR{S} <Rd>, <Rm>, #<imm5>     ; 用立即数 imm5 (1-32) 指定移位位数

注意 :立即数移位范围是 1-32 。当 #imm5 为 32 时,结果为 0,且最后移出的位进入 C 标志。

工作原理

复制代码
Before:  Rm = [b31 b30 ... b1 b0]
After:   Rd = [0 ... 0  b31 ... bn]    <-- n 个 0 填入高位
                \___________/
                向右移动 n 位

最后移出的那一位(原 bn-1 位)会进入 CPSRC(进位)标志。

示例

armasm 复制代码
MOV     R1, #20         ; R1 = 20 (二进制 00010100)
LSR     R0, R1, #2      ; R0 = R1 >> 2
; 计算过程: 00010100 >> 2 = 00000101
; 结果: R0 = 5 (20 / 4)
armasm 复制代码
MOV     R2, #0x80000001 ; R2 = 0x80000001
LSRS    R3, R2, #1      ; R3 = R2 >> 1,并更新标志
; 计算过程: 1000...0001 >> 1 = 0100...0000
; 结果: R3 = 0x40000000
; 标志变化:最后移出的 '1' 进入 C 标志,所以 C = 1。结果非负非零,所以 N=0, Z=0。

关键点与进阶用法

  1. 移位量为 0 :对于 LSL #0,操作数不变,但可能影响 C 标志(C 标志会被设置为 ALU 的进位输出,在移位量为0的特定情况下,其行为有详细规定,通常编程时可忽略此边界情况)。对于 LSR #0,在 ARM 中实际表示 LSR #32,这是一个特例。

  2. 桶形移位器 :ARM 处理器有一个称为"桶形移位器"的硬件单元,这使得移位操作可以在一个时钟周期内完成 ,并且可以与其他指令结合而无额外开销。这是 ARM 指令集高效的关键之一。

  3. 与其他指令结合(灵活的第二操作数)

    这是 ARM 汇编最常用的特性之一。几乎所有的数据处理指令(ADD, SUB, MOV, CMP, AND, ORR 等)的第二个操作数都可以先进行移位,然后再参与运算。

    armasm 复制代码
    ADD R0, R1, R2, LSL #2    ; R0 = R1 + (R2 * 4)
    CMP R3, R4, LSR #3        ; 比较 R3 和 (R4 / 8)
    MOV R5, R6, ROR #4        ; R5 = 将 R6 循环右移 4 位后的值 (ROR是另一种移位)

    这种结合极大地增强了指令的表达能力,一条指令完成了"移位+运算"。

  4. 与算术右移 ASR 的区别

    • LSR 是逻辑右移,高位补 0 。用于处理无符号数
    • ASR(算术右移)高位用原最高位(符号位)填充 。用于保持有符号数的符号,相当于有符号除法。

总结

指令 全称 方向 填充值 主要数学意义 典型用途
LSL Logical Shift Left 向左 低位补 0 乘以 2^n 快速乘法、位组装、掩码生成
LSR Logical Shift Right 向右 高位补 0 无符号除以 2^n 快速无符号除法、位提取、无符号数处理

掌握 LSLLSR 是理解 ARM 高效编程和位操作的基础。务必通过实践来熟悉它们的行为,尤其是与条件标志和与其他指令结合使用的方式。

相关推荐
STCNXPARM14 小时前
Android14显示系统 - ARM GPU完全剖析
arm开发·arm·gpu·android显示
fengye2071611 天前
板凳----------(枯藤 )vs2026+win10(第六章-4)
汇编
-曾牛1 天前
【汇编语言入门】从第一个加法程序吃透汇编核心基础
汇编·单片机·嵌入式硬件·汇编语言·病毒分析·lcx·逆向开发
___波子 Pro Max.1 天前
ARM栈展开原理解析
arm开发
切糕师学AI2 天前
ARM 汇编指令:ROR(循环右移)
汇编·arm开发
运维老司机2 天前
ARM 架构源码编译部署 MySQL 5.7.42完整实战文档
arm开发·mysql·架构
路溪非溪2 天前
Linux驱动中的红外遥控子系统
linux·arm开发·驱动开发
草莓熊Lotso3 天前
Python 库使用全攻略:从标准库到第三方库(附实战案例)
运维·服务器·汇编·人工智能·经验分享·git·python
不染尘.3 天前
操作系统发展史和常见习题汇总
arm开发·嵌入式硬件·draw.io