汇编之分支跳转指令

  • 顺序执行:硬件自动修改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
相关推荐
2601_962296512 天前
C/C++:编译全过程——预处理、编译、汇编、链接(包含预处理指令:宏定义,文件包括、条件编译)
汇编·预处理·链接·c/c++·编译过程
Freak嵌入式3 天前
Pico PIO 汇编语法深度详解:标识符、指令、伪指令全解析
汇编·stm32·单片机·嵌入式硬件·fpga开发·硬件架构
kyle~8 天前
x86 汇编LOCK前缀 --- 硬件架构向软件提供的核心同步原语
汇编·c++·性能优化·硬件架构·实时系统
典典分享指南9 天前
飞书 + 企业微信 + 微信文档多端协同实践指南
汇编·flask·intellij-idea·fastapi
zhangzhangkeji11 天前
笔记 34 - 7 :网卡 DM9000AE; uboot 网络协议栈,里的函数调用流程
arm
zhangzhangkeji14 天前
笔记 30 - 4 :rootfs 配置文件定制,etc / profile,与挂载测试
arm
极客互动API14 天前
企业微信 iPad 协议服务搭建与 AI 回调实战
网络·汇编·人工智能·微信·企业微信·ipad
zhangzhangkeji14 天前
笔记 34 - 3 :网卡 DM9000AE;16 位下的引脚功能,引脚映射到 SROMC,到 GPIO
arm
深念Y17 天前
订阅管理及节点过滤实践(技术笔记)
linux·网络·arm·优化·日志·工具·soc
zhangzhangkeji18 天前
笔记 28 : linux 里 Kconfig 语法详解
arm