AVR汇编(六):分支指令

分支指令用于改变程序的执行流,分为无条件分支和条件分支两类。

无条件分支指令

JMP

JMP 指令用于无条件跳转,类似于C中的 goto 关键字, JMP 指令的跳转范围为[0, 4M-1]字。

RJMP 指令用于相对跳转,跳转范围为当前位置[-2K, 2K-1]字。

IJMP 指令用于间接跳转,跳转的目的地址存放在 Z 寄存器中(记住单位是字)。

例如:

    JMP f2             ; 跳转到f2
f1:
RJMP f3 ; 跳转到f3
f2:
LDI ZL, lo8(f1)
LDI ZH, hi8(f1) ; Z = f1
CLC
ROR ZH
ROR ZL ; Z = Z >> 1
IJMP ; 跳转到f1
f3:
RJMP f2 ; 跳转到f2

注意:实测在GNU汇编下, IJMP 指令中不能直接把标签赋值给 Z 寄存器,因为标签表示的地址的单位是字节,而 Z 寄存器中存放的应该是字地址,所以要将标签右移一位传给 Z 寄存器。而 JMP 指令和 RJMP 指令则可以直接传标签。

CALL / RET

CALL 指令用于子程序调用,和 JMP 指令一样,也可以实现程序跳转,但是 CALL 指令在跳转之前会将下一条指令的地址(返回地址)压入栈中。 CALL 指令的跳转范围为[0, 64K-1]字。

RCALL 指令用于相对子程序调用,跳转范围为当前位置[-2K, 2K-1]字。

ICALL 指令用于间接子程序调用,子程序的地址存放在 Z 寄存器中(记住单位是字)。

RET 指令用于子程序返回,先将返回地址从栈中弹出,然后进行跳转。

RETI 指令用于中断子程序返回,和 RET 指令不同的是,它还会设置全局中断使能位 I

例如:

    CALL f1            ; 调用f1子程序
RCALL f1 ; 调用f1子程序
LDI ZL, lo8(f1)
LDI ZH, hi8(f1) ; Z = f1
CLC
ROR ZH
ROR ZL ; Z = Z >> 1
ICALL ; 调用f1子程序
f1:
...
RET ; 子程序返回 XXX_IRQHandler:
...
RETI ; 中断子程序返回

条件分支指令

CP

CP 指令用于比较,实际上就是只影响标志位而不保存结果的减法操作。后缀带 C 表示带进位比较,后缀带 I 表示与立即数比较,后缀带 SE 表示如果相等,则跳过下一条指令。

例如:

    LDI R16, 0x01
LDI R17, 0x02
CP R16, R17
BRLT f1 ; 1 < 2,跳转到f1
RJMP f3 ; 不会执行
f1:
CPI R16, 0x01
BREQ f2 ; 1 == 1,跳转到f2
RJMP f3 ; 不会执行
f2:
LDI R17, 0x01
CPSE R16, R17 ; 1 == 1,跳过下一条指令
RJMP f3 ; 不会执行
SEC
CPC R16, R17
BRLT f3 ; 1 < 1 + C(1),跳转到f3
RJMP f1 ; 不会执行
f3:
RJMP f3

SBxx

形如 SBxx 的指令根据寄存器中的某一位来选择跳过执行下一条指令, SBRC / SBRS 指令根据的是通用寄存器中的位的清除/设置状态,而 SBIC / SBIS 指令根据的是I/O寄存器中的。

例如:

f1:
LDI R16, 0xAA
SBRS R16, 1 ; R16.1 == 1,跳过下一条指令
RJMP f1 ; 不会执行
SBIC PINB, 2 ; 如果PB2输入为低电平,跳过下一条指令
RJMP f1

BRxx

形如 BRxx 的指令用于根据条件改变程序执行流,支持的条件具体见下表:

BRxx 类的指令一般和 CPSUB 指令配合使用。

例如:

f1:
LDI R16, 0X01
LDI R17, 0X02
CP R16, R17
BRLO f2 ; 0x01 < 0x02,跳转到f2
RJMP f1 ; 不会执行
f2:
CPI R16, 0x01
BRSH f3 ; 0x01 == 0x01,跳转到f3
RJMP f1 ; 不会执行
f3:
RJMP f3

参考资料

  1. ATmega328P Datasheet
  2. AVR Instruction Set Manual

AVR汇编(六):分支指令的更多相关文章

  1. AVR之BOOTLOADER技术详解(转)

    源:http://blog.csdn.net/zhenhua10/article/details/6442412 ATmega128具备引导加载支持的用户程序自编程功能(In-System Progr ...

  2. Markdown 常用语言关键字

    Markdown 语法高亮支持的语言还是比较多的,记下来备用. 语言名 关键字 Bash bash CoffeeScript coffeescript C++ cpp C# cs CSS css Di ...

  3. 32位汇编第六讲,OllyDbg逆向植物大战僵尸,快速定位阳光基址

    32位汇编第六讲,OllyDbg逆向植物大战僵尸,快速定位阳光基址 一丶基址,随机基址的理解 首先,全局变量的地址,我们都知道是固定的,是在PE文件中有保存的 但是高版本有了随机基址,那么要怎么解决这 ...

  4. PC逆向之代码还原技术,第六讲汇编中除法代码还原以及原理第二讲,被除数是正数 除数非2的幂

    目录 一丶简介 二丶代码还原讲解 1.被除数无符号 除数非2的幂 2.被除数无符号 除数为特例7 三丶代码还原总结 一丶简介 上一篇博客说的除2的幂. 如果被除数是有符号的,那么会进行调整,并使用位操 ...

  5. 汇编学习(六)——代码转换程序

    (一)逻辑运算指令 一.双操作数逻辑运算指令 1.指令格式: AND dst,src ; "与"运算, OR dst,src ; "或"运算 XOR dst,s ...

  6. arm汇编学习(六)---跳转到thumb状态

    通常函数返回使用 pop {r7,pc}或bx lr等方式(bx,b类似jmp为跳转指令,但bx可以指定跳转区域究竟为thumb还是arm指令.thumb指令指令的时候,直接填写该地址却总是产生SIG ...

  7. 计算机系统6-> 计组与体系结构3 | MIPS指令集(中)| MIPS汇编指令与机器表示

    上一篇计算机系统5-> 计组与体系结构2 | MIPS指令集(上)| 指令系统从顶层讲解了一个指令集 / 指令系统应当具备哪些特征和工作原理.这一篇就聚焦MIPS指令集(MIPS32),看看其汇 ...

  8. v87.01 鸿蒙内核源码分析 (内核启动篇) | 从汇编到 main () | 百篇博客分析 OpenHarmony 源码

    本篇关键词:内核重定位.MMU.SVC栈.热启动.内核映射表 内核汇编相关篇为: v74.01 鸿蒙内核源码分析(编码方式) | 机器指令是如何编码的 v75.03 鸿蒙内核源码分析(汇编基础) | ...

  9. 20145212——GDB调试汇编堆栈过程分析

    GDB调试汇编堆栈过程分析 测试代码 #include <stdio.h> short val = 1; int vv = 2; int g(int xxx) { return xxx + ...

  10. arm汇编指令

    ARM处理器的指令集可以分为跳转指令.数据处理指令.程序状态寄存器(PSR)处理指令.加载/存储指令.协处理器指令和异常产生指令6大指令 一.跳转指令 跳转指令用于实现程序流程的跳转 跳转指令分类 Ⅰ ...

随机推荐

  1. docker无法启动,报错grpc: addrConn.createTransport failed to connect to {unix:///run/containerd/containerd.

    docker无法启动,报错.k8s的pod镜像加载失败. 解法方法: 删除/var/lib/docker/和/var/lib/containerd/ 这两个文件夹,重起docker服务. 问题完美解决 ...

  2. 2022-04-30:在无限的平面上,机器人最初位于 (0, 0) 处,面朝北方。注意: 北方向 是y轴的正方向。 南方向 是y轴的负方向。 东方向 是x轴的正方向。 西方向 是x轴的负方向。 机器人

    2022-04-30:在无限的平面上,机器人最初位于 (0, 0) 处,面朝北方.注意: 北方向 是y轴的正方向. 南方向 是y轴的负方向. 东方向 是x轴的正方向. 西方向 是x轴的负方向. 机器人 ...

  3. 2021-07-14:接雨水。给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

    2021-07-14:接雨水.给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 福大大 答案2021-07-14: 左右指针向中间移动.左指针是左边柱 ...

  4. 2021-12-04:公交路线。给你一个数组 routes ,表示一系列公交线路,其中每个 routes[i] 表示一条公交线路,第 i 辆公交车将会在上面循环行驶。 例如,路线 routes[0]

    2021-12-04:公交路线.给你一个数组 routes ,表示一系列公交线路,其中每个 routes[i] 表示一条公交线路,第 i 辆公交车将会在上面循环行驶. 例如,路线 routes[0] ...

  5. Spectre.Console-处理依赖注入

    引言 之前说的做自动记录 Todo 执行过程中消耗的时间的Todo 项目,由于想持续保持程序执行,就放弃了 Spectre.Console.Cli,后来随着命令越来越多,自己处理觉得很是麻烦,想了想要 ...

  6. 基于渗透的python

    Python for Pentesters 还记得开始学习编程的C,虽然淡忘,但思想仍在. 子域名枚举 request库 import pyfiglet import requests import ...

  7. 【实战分享】使用 Go 重构流式日志网关

    项目背景 分享之前,先来简单介绍下该项目在流式日志处理链路中所处的位置. 流式日志网关的主要功能是提供 HTTP 接口,接收 CDN 边缘节点上报的各类日志(访问日志/报错日志/计费日志等),将日志作 ...

  8. 翻译:REST 和 gRPC 详细比较

    译者注:在微服务架构设计,构建API和服务间通信技术选型时,对 REST 和 gRPC 的理解和应用还存在知识盲区,近期看到国外的这篇文章:A detailed comparison of REST ...

  9. 一次性掌握innodb引擎如何解决幻读和不可重复读

    了解mysql的都知道,在mysql的RR(可重复)隔离级别下解决了幻读和不可重复.你知道RR下是怎么解决的吗,很多人会回答是通过MVCC和next-key解决的,具体是怎么解决的,今天来重点分析下. ...

  10. 前端学习C语言 - 初级指针

    初级指针 本篇主要介绍:指针和变量的关系.指针类型.指针的运算符.空指针和野指针.指针和数组.指针和字符串.const 和指针.以及gdb 调试段错误. 基础概念 指针是一种特殊的变量.存放地址的变量 ...