- 顺序执行:硬件自动修改PC寄存器, PC = PC+4
- 在ARM中有两种方式可以跳转:
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
z80
复制代码
b{l}x{cond} <Rm>
Rm,通用寄存器, 存放的是要跳转的地址
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 @ 汇编结束标记(告诉汇编器程序结束)
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
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