首页 > 编程语言 >AVR汇编(六):分支指令

AVR汇编(六):分支指令

时间:2023-08-14 14:55:37浏览次数:41  
标签:汇编 f3 f1 AVR 指令 跳转 子程序 RJMP

AVR汇编(六):分支指令

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

无条件分支指令

JMP

image.png

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

image.png

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

image.png

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

image.png

形如 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

image.png

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

image.png

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

标签:汇编,f3,f1,AVR,指令,跳转,子程序,RJMP
From: https://www.cnblogs.com/chinjinyu/p/17628626.html

相关文章

  • 在MQTT通信中用AT指令发送json格式的内容
    在MQTT通信中使用AT指令发送JSON格式的内容,需要使用适用于你的设备的AT指令集,并按照以下步骤进行操作:建立MQTT连接:首先,使用AT指令建立与MQTT代理服务器的连接。这可能涉及到设置服务器地址、端口、用户名、密码等参数。创建JSON数据:在你的设备中,使用AT指令创建要发送的JSON格式的......
  • 1-1汇编语言程序上机调试
    .MODELTINY.STACK100.DATA.CODESTART: MOVAX,@DATA MOVDS,AX MOVES,AX NOP MOVCX,100HMOVSI,3000HMOVDI,6000HCALLMoveMOVCX,100HMOVSI,3000HMOVDI,......
  • AVR汇编(五):算术和逻辑指令
    AVR汇编(五):算术和逻辑指令算术运算指令AVR中对于算术运算提供了加法、减法和乘法指令,没有除法指令。ADDADD指令用于执行加法操作,相关的变体指令有:一般加法ADD、带进位加法ADC、16位立即数加法ADIW。例如:LDIR16,0x01;R16=0x01LDIR17,0x02;R17=0x02......
  • 【8月摸鱼计划】4G模块相关的at指令
    #连接4g模块cu-l/dev/cuaU0.3#设置成ECM模式,设置成功后会自动重启模块,需要重新连接4g模块at+qcfg=“usbnet”,1#设置APN,移动:cmnet,联通:3gnet,电信:ctnetat+cgdcont=1,“IP”,“ctnet”#重启模块at+cfun=1,1#检查模块的模式,应返回1at+qcfg=“usbnet”#检查sim卡,应该返回READYat......
  • 管理指令
    重启系统reboot 直接重启shutdown可以指定时间 shutdown-rnow立即重启shutdown-r23:30指定时间重启系统服务管理systemctl防火墙查看防火墙状态systemctlstatusfirewalld 停止防火墙#systemcltstopfirewalld 启动与关闭后台服务systemctll......
  • 汇编-错误代码
      errorA2005:Symbolismultidefined:DATA此错误信息提示DATA符号重复定义了。 errorA2009:Symbolnotdefined:NO汇编提示标号NO没有定义        ......
  • 独特的控制码学习功能,可自行修改控制码指令控制键盘
    新推出的高清视频会议控制键盘(控制器),采用工业四维精密摇杆,采用RJ45、RS422、RS485、RS232多种控制接口,最多可接255个摄像机;独特的控制码学习功能,可以自行修改控制码指令;所有摄像机参数均可通过按键操作程序完成设置;金属壳体,硅胶按键设计;液晶中英文显示,带按键声音提示,实时显示解码......
  • AVR汇编(四):数据传送指令
    AVR汇编(四):数据传送指令AVR指令主要分为五类:算术和逻辑指令、分支指令、位操作指令、数据传送指令、MCU控制指令,今天我们先来认识其中最常用的数据传送指令。汇编程序的编写、编译和调试学习任何技术都离不开实践,汇编语言也是如此。在正式学习指令前,我们先来体验一下汇编程序从......
  • Nginx中的rewrite指令(break,last,redirect,permanent)
    rewite在server块下,会优先执行rewrite部分,然后才会去匹配location块server中的rewritebreak和last没什么区别,都会去匹配location,所以没必要用last再发起新的请求,可以留空location中的rewirte:不写last和break-那么流程就是依次执行这些rewrite1.rewritebreak-url重写后,直......
  • C++ #pragma once指令:保护C++头文件不被重复包含
    一、#ifndef/#define/#endif指令的问题在C++中,头文件的作用就是将代码以模块的形式组织起来,便于复用和维护。但是,头文件很容易出现重复定义的问题。比如,某个头文件被多个源文件包含,这些源文件又有可能被其他源文件包含,那么就有可能出现一个头文件被重复包含的情况。这样就会......