为什么我在 proteus 中收到此错误:“PC=0x002A 处的操作码 0xFFFF 无效”

Muh*_*mar 2 microcontroller assembly avr atmega32

我用汇编语言为 avr atmega328P 编写了这段代码。它使用按钮打开和关闭 LED,但在 proteus 中我收到此错误:

PC=0x002A 处的无效操作码 0xFFFF

这是我的代码:

.INCLUDE "M328Pdef.inc"


ldi r16,HIGH(RAMEND)
out SPH, R16
ldi r16,LOW(RAMEND)
out SPL, R16

start:
ldi r16,0xFF
out DDRB,r16
ldi r17,0x00
out DDRD,r17
ldi r21,0x00
ldi r23,0x01

Forever:
in r20,PIND
cp r20,r21
BREQ ledon
cp r20,r23
BREQ ledoff
rjmp Forever


ledon:
ldi r22,0x01
out PORTB,r22 
ret

ledoff:
ldi r24,0x00
out PORTB,r24
ret

Run Code Online (Sandbox Code Playgroud)

有人有解决办法吗?

ema*_*uts 10

问题就在这里:

BREQ ledon  ; branch
cp r20,r23
BREQ ledoff ; branch
rjmp Forever

ledon:
ldi r22,0x01
out PORTB,r22 
ret ; return from subroutine, but never used [R]CALL.

ledoff:
ldi r24,0x00
out PORTB,r24
ret ; return from subroutine, but never used [R]CALL.
Run Code Online (Sandbox Code Playgroud)

您正在分支到ledonresp。ledoff,这只是一个条件跳转。但在各个块的末尾,您使用的ret方式就好像通过[r]call.

将从ret堆栈中弹出 2 个字节并将它们用作要返回的字地址。代码目标很可能具有未初始化的闪存,其中包含 0xff,并且两个 0xff 是 0xffff,这不是合法的 AVR 操作码。ret0x002a 是最后一个发出非法跳转的字节地址。

要修复,您可以rjmp Forever代替ret,但这取决于您想要通过代码实现的目标。