我正在开发一个小程序,以学习如何在 Atmel Studio GCC 中混合 C 和汇编。基本上我正在编写一个 C 程序来启动汇编中的堆栈指针。当我构建它时,我不断收到错误“操作数超出范围”。我已经在程序中多次启动堆栈指针,但无法让它在该程序的“.s”文件中工作。我已经让程序与“.s”文件中的不同寄存器一起工作,所以我不认为这是两个文件之间的连接。任何帮助将不胜感激。
主.c:
#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
extern void setStackPointer(void);
int main(void)
{
DDRB |= 0x20;
setStackPointer();
while (1)
{
PORTB = 0x20;
_delay_ms(500);
PORTB = 0x00;
_delay_ms(500);
}
}
汇编器1.s:
#define _SFR_ASM_COMPAT 1
#define _SFR_OFFSET 0
#include <avr/io.h>
.global setStackPointer
setStackPointer:
ldi r18, lo8(RAMEND-0x20)
out SPL, R18
ldi R18, hi8(RAMEND-0x20)
out SPH, R18
ret
最佳答案
这里有几个问题。
首先,乔·布莱克爵士的评论是正确的:没有理由
从 RAMEND
中减去 0x20
。我的意思是,除非你想分开 32
RAM 末尾的字节...
其次,自己设置堆栈指针是没有意义的。在大多数
最新的AVR,包括ATmega328P,SP
会自动初始化
由硬件通过 RAMEND
实现。 C.f.数据表。如果不是的话
足够了,它由 C 运行时再次初始化,正常运行
如果您编译,则链接到您的程序(即使是 100% 汇编程序)
与 gcc 一起使用。
三、来自avr-libc documentation :
For more backwards compatibility, insert the following at the start of your old assembler source file:
#define __SFR_OFFSET 0
This automatically subtracts 0x20 from I/O space addresses, but it's a hack, so it is recommended to change your source: wrap such addresses in macros defined here, as shown below. After this is done, the
__SFR_OFFSET
definition is no longer necessary and can be removed.
编写该代码的推荐方法是:
setStackPointer:
ldi r18, lo8(RAMEND)
out _SFR_IO_ADDR(SPL), r18
ldi r18, hi8(RAMEND)
out _SFR_IO_ADDR(SPH), r18
ret
如果你真的想使用旧的技巧,请写
#define __SFR_OFFSET 0
在程序的开头。并且注意双 宏名称开头加下划线。
关于avr - Atmel Studio AVR 操作数超出范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47598918/