汇编之分支跳转指令

  • 顺序执行:硬件自动修改PC寄存器, PC = PC+4
  • 在ARM中有两种方式可以跳转:
    • 直接向PC寄存器写入目标地址值
z80 复制代码
mov pc, #0xff000000 @跳转到0xff000000的位置去执行
复制代码
- 专门的跳转指令
    * B/BL
    * BX/BLX

B/BL

z80 复制代码
b{l}{cond} <target>
  l, 自动将下一条指令的地址保存到LR寄存器, 子程序调用的一个基本但常用的手段
  cond, 条件码
  target,目标地址
z80 复制代码
/*
 * 比较两个寄存器的值,若r0 < r1则交换它们,最后执行无意义的加法并进入死循环
 */
.text               @ 声明代码段,后续内容为可执行指令
.global _start      @ 将_start符号声明为全局可见,作为程序入口点

_start:             @ 程序入口标签
  mov r0, #10       @ 将立即数10加载到寄存器r0中 (r0 = 10)
  mov r1, #20       @ 将立即数20加载到寄存器r1中 (r1 = 20)
  cmp r0, r1        @ 比较r0和r1的值 (执行 r0 - r1,仅更新状态寄存器CPSR)
  bllt swap         @ 条件分支指令:若r0 < r1 (LT=Less Than),则跳转到swap标签,同时将返回地址存入lr寄存器
  add r5, r6, r7    @ 执行加法操作:r5 = r6 + r7 (注:r6/r7未初始化,值为随机数)
  b stop            @ 无条件跳转到stop标签

swap:               @ 交换r0和r1值的函数标签
  mov r2, r0        @ 临时保存r0的值到r2 (r2 = r0)
  mov r0, r1        @ 将r1的值赋给r0 (r0 = r1)
  mov r1, r2        @ 将临时保存的r0值(r2)赋给r1 (r1 = r2)
  mov pc, lr        @ 将链接寄存器lr的值赋给程序计数器pc,实现函数返回

stop:               @ 程序终止标签
  b .               @ 无条件跳转到当前地址(死循环),使程序暂停在此处
.end                @ 汇编程序结束标记
  • b/bl 指定后面直接给定了要跳转的地址, 包括地址在内的所有信息会被翻译为一条32bit的机器指令,注定跳转范围受限:±32M

BX/BLX

  • X, 带状态切换的分支跳转指令
z80 复制代码
b{l}x{cond} <Rm>
  Rm,通用寄存器, 存放的是要跳转的地址
  • 跳转范围不受限 0~4G随便跳
z80 复制代码
/*
* 程序功能:比较R0和R1的值,若R0 < R1则交换两者,最后原地死循环
*/
.text                   @ 声明代码段(存放可执行指令)
.global _start          @ 将_start声明为全局符号,作为程序入口

_start:                     @ 程序入口标签
    mov     r0, #10         @ 初始化R0寄存器为立即数10(第一个比较数)
    mov     r1, #20         @ 初始化R1寄存器为立即数20(第二个比较数)
    
    cmp     r0, r1          @ 比较指令:执行R0 - R1,仅更新CPSR状态位(不保存结果)
                            @ 会影响的标志位:N(负)、Z(零)、C(进位)、V(溢出)
    
    blcc    swap            @ 带链接条件跳转:cc(Carry Clear,C=0)即无进位,对应R0 < R1
                            @ 若R0 < R1则跳转到swap子程序,同时将返回地址(当前指令下一条)存入LR(R14)
    
    add     r3, r4, r5      @ 加法指令:R3 = R4 + R5(注:R4/R5未初始化,结果为随机值)
    b       .               @ 无条件跳转到当前地址(.表示当前PC值),实现原地死循环

swap:                       @ 子程序:交换R0和R1的值
    mov     r2, r0          @ 第一步:将R0的值暂存到R2(临时寄存器)
    mov     r0, r1          @ 第二步:将R1的值赋值给R0
    mov     r1, r2          @ 第三步:将R2中暂存的原R0值赋值给R1,完成交换
    ; mov   pc, lr          @ 传统返回方式:直接将LR的值写入PC,等价跳转(已注释,推荐用bx lr)
    bx      lr              @ 带状态切换的返回:将LR的值写入PC,返回调用处
                            @ bx支持ARM/Thumb指令集切换,兼容性更强,是推荐的返回方式

    .end                    @ 汇编结束标记(告诉汇编器程序结束)
  • 练习:求1到10的累加和结果保存到r0
z80 复制代码
.text
.global _start @将_start声明为全局的
_start:
  mov r0, #0
  mov r1, #10 @循环次数
loop:
  add r0, r0, r1
  sub r1, r1, #1
  cmp r1, #0
  bne loop
  b .
.end
  • 练习:求1到10的累加和结果保存到r0
z80 复制代码
.text
.global _start @将_start声明为全局的
_start:mov r0, #8
  mov r1, #36
loop:
  cmp r0, r1
  sublt r1, r1, r0
  subgt r0, r0, r1
  bne loop
  b .
.end
相关推荐
XINVRY-FPGA1 天前
XC7Z020-2CLG400I Xilinx AMDZynq-7000 FPGA
嵌入式硬件·fpga开发·arm·硬件工程·dsp开发·fpga
梁洪飞1 天前
armv7a和uboot里面的重要概念
arm开发·嵌入式硬件·arm
FreakStudio2 天前
一行命令搞定驱动安装!MicroPython 开发有了自己的 “PyPI”包管理平台!
python·stm32·单片机·嵌入式·arm·电子diy
leluckys3 天前
swift- Swift中常见的面试题
开发语言·汇编·swift
toradexsh3 天前
基于 NXP iMX8MP ARM平台安装测试 Openclaw
linux·docker·arm·nxp·openclaw
bcbobo21cn3 天前
学习DOS汇编显示系统日期时间程序
汇编·dos中断21h·2ah功能·2ch功能
职豚求职小程序4 天前
东软集团题库笔试测评系统练习笔试2026新版
大数据·汇编·人工智能
我在人间贩卖青春19 天前
汇编之伪指令
汇编·伪指令
我在人间贩卖青春19 天前
汇编之伪操作
汇编·伪操作
济61719 天前
FreeRTOS基础--堆栈概念与汇编指令实战解析
汇编·嵌入式·freertos