汇编之分支跳转指令

  • 顺序执行:硬件自动修改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
相关推荐
我在人间贩卖青春4 小时前
汇编之加载存储指令
汇编·arm·寄存器加载存储
我在人间贩卖青春5 小时前
汇编之状态寄存器访问指令
汇编·arm·状态寄存器
我在人间贩卖青春5 小时前
汇编之软中断指令和协处理指令
汇编·arm·软中断·协处理
我在人间贩卖青春7 小时前
汇编之数据处理指令
汇编·arm·数据处理指令
白太岁1 天前
操作系统开发:(11) RTOS 与 GPOS 的分界线:MMU
c语言·开发语言·汇编·arm开发·系统架构
枷锁—sha2 天前
【pwn系列】Pwndbg 汇编调试实操教程
网络·汇编·笔记·安全·网络安全
白太岁2 天前
C++:(4) 内存布局、编译流程、关键字及其链接性
c语言·汇编·jvm·c++
fly的fly3 天前
浅析 QT远程部署及debug方案
qt·物联网·arm
real_ben_ladeng5 天前
程序人生—Hello’s P2P 2dc736403375808d93f9c97fc816f2f8
c语言·汇编·硬件架构