AVR的指令与汇编系统
AVR单片机指令系统是RISC结构的精简指令集,CISC结构存在指令系统不等长,指令数多,CPU利用效率低,执行速度慢等缺陷。
ATmega16共有131条指令,按功能可分为五大类,它们是:
A.算术和逻辑运算指令(28 条);
B.比较和跳转指令(36 条);
C.数据传送指令(35 条);
D.位操作和位测试指令(28 条);
E.MCU控制指令(4 条)。
AVR一条指令的长度大多数为16位,还有少部分为32位。
AVR的指令的一般格式为:
操作码用于指示CPU执行何种操作,是加法还是减法,是数据传送还是数据移位。
一条指令可以只有操作码,或第一操作数。
AVR的汇编语句的格式:
(1) [标号:] 伪指令 [操作数] [;注释]
(2) [标号:] 指令 [操作数] [;注释]
1.AVR指令的寻址方式和寻址空间
指令的一个重要组成部分是操作数。指令给出参与运算数据的方式称为寻址方式。CPU执行指令时,首先要根据地址获取参加操作的操作数,然后才能对操作数进行操作,操作的结果还要根据地址保存在相应的储存器或寄存器中。
下面介绍部分AVR的部分指令及寻址方式:
(1)单寄存器寻址 例:INC Rd ;操作:Rd←Rd+1
INC R5 ;将寄存器R5内容加1回放。
(2)双寄存器寻址 例:ADD Rd, Rr ;操作:Rd←Rd+Rr
ADD R0, R1 ;将R0和R1寄存器内容相加,结果回放R0。
(3)I/O寄存器直接寻址 例:IN Rd, P ;操作:Rd←P。
IN R5, $3E ;读 I/O 空间地址为$3E寄存器(SPH)的内容,放入寄存器R5。
(4)数据存储器空间直接寻址 例:LDS Rd, K ;操作:Rd←(K)
LDS R18, $100 ;读地址为$100的SRAM中内容,传送到R18中。
(5)数据存储器空间的寄存器间接寻址 例:LD Rd, Y ;操作:Rd←(Y),把以Y为指针的SRAM的内容送Rd。
LD R16, Y ;设Y=$0567,即把SRAM地址为$0567的内容传送到R16中。
(6)程序存储器空间取常量寻址
例:LPM ;操作:R0←(Z),即把以Z为指针的程序存储器的内容送R0。
若 Z=$0100,即把地址为$0080的程序存储器的低字节内容送R0。
若 Z=$0101,即把地址为$0080的程序存储器的高字节内容送R0。
例:LPM R16, Z ;操作:R16←(Z),即把以Z为指针的程序存储器的内容送R16。
若 Z=$0100,即把地址为$0080 的程序存储器的低字节内容送R16。
若 Z=$0101,即把地址为$0080 的程序存储器的高字节内容送R16。
(7)程序存储器空间写数据寻址
例:SPM ;操作:(Z)←R1:R0,把 R1:R0 内容写入以 Z 为指针的程序存储器单元。
(8)程序存储器空间直接寻址
例:JMP $0100 ;操作:PC←$0100。程序计数器 PC 的值设置为$0100,接下来执行程序存储器$0100 单元的指令代码。
例:CALL $0100 ;操作:STACK←PC+2; SP← SP-2; PC←$0100。先将程序计数器 PC 的当前值加 2 后压进堆栈(CALL 指令为 2 个字长),堆栈指针计数器 SP 内容减 2,然后 PC 的值为$0100,接下来执行程序存储器$0100 单元的指令代码。
(9)程序存储器空间相对寻址
例:RJMP $0100 ;操作:PC←PC+1+$0100。若当前指令地址为$0200(PC=$0200),即把$0301 送程序计数器 PC,接下来执行程序存储器$0301 单元的指令代码。
例:RCALL $0100 ;操作:STACK←PC+1;SP←SP-2;PC←PC+1+$0100。若当前指令地址为$0200(PC=$0200),先将程序计数器 PC 的当前值加 1 后压进堆栈,堆栈指针计数器SP 内容减 2,然后 PC 的值为$0301,接下来执行程序存储器$0301 单元的指令代码。
(10)数据存储器空间堆栈寄存器 SP 间接寻址
例:PUSH R0 ;操作:STACK←R0;SP←SP-1。若当前 SP=$10FF,先把寄存器 R0 的内容送到 SRAM 的$10FF 单元,再将 SP 内容减 1,即 SP=$10FE。
例:POP R1 ;操作:SP←SP+1;R1←STACK。若当前 SP=$10FE,先将 SP 内容加 1,再把 SRAM 的$10FF 单元内容送到寄存器 R1,此时 SP=$10FF。
此外,在 CPU 响应中断和执行 CALL 一类的子程序调用指令(SP = SP-2),以及执行中断返回 IRET 和子程序返回 RET 一类的子程序返回指令中(SP = SP+2),都隐含着使用堆栈寄存器 SP 间接寻址的方式。
2.AVR汇编器伪指令
在汇编语言程序中可以使用一些伪指令。伪指令不属于 CPU 指令集,编译时并不产生实际的目标机器操作代码,只是用于在汇编程序中对地址、寄存器、数据、常量等进行定义说明,以及对编译过程进行某种控制等。AVR 的指令系统不包括伪指令,伪指令通常由汇编编译系统给出。
伪指令一般以 . 开头,如:
.DSEG ;RAM 数据段(SRAM)
var1: .BYTE 1 ;保留 1 个字节的存储单元,用 var1 标识
table: .BYTE tab_size ;保留 tab_size 个字节的存储空间
.CSEG ;代码段开始(Flash)
ldi r30, low(var1) ;将保留存储单元 var1 起始地址的低 8 位装入 Z
ldi r31, high(var1) ;将保留存储单元 var1 起始地址的高 8 位装入 Z
ld r1, Z ;将保留存储单元的内容读到寄存器 R1