Atmel Studio AVR操作数超出范围

时间:2017-12-01 17:53:42

标签: avr atmelstudio

我正在开发一个小程序,以学习如何在Atmel Studio GCC中混合使用C和Assembly。基本上我正在编写一个C程序来启动程序集中的堆栈指针。当我构建它时,我不断收到错误“操作数超出范围”。我已在程序中多次启动堆栈指针,但无法在该程序的“.s”文件中使用它。我已经让程序在“.s”文件中使用不同的寄存器,所以我不认为这是两个文件之间的连接。任何帮助将不胜感激。

MAIN.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);
        }
    }

Assembler1.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

1 个答案:

答案 0 :(得分:1)

这里有几个问题。

首先,乔布莱克爵士的评论是对的:没有理由 从0x20中减去RAMEND。我的意思是,除非你想分开32 RAM末尾的字节......

其次,自己设置堆栈指针没有意义。最多的 最近的AVR,包括ATmega328P,SP会自动初始化 由RAMEND的硬件。 C.F.数据表。如果不是这样的话 足够的,它由C运行时再次初始化,正常运行 如果编译,链接到您的程序(甚至是100%汇编程序) 它与gcc。

第三,来自avr-libc documentation

  

要获得更多向后兼容性,请在开头插入以下内容   旧的汇编源文件:

     

#define __SFR_OFFSET 0

     

这会自动从I / O空间地址中减去0x20,但它是a   hack,所以建议更改你的源:包装这样的地址   在此处定义的宏中,如下所示。完成后,   <{1}}定义不再是必需的,可以删除。

编写该代码的推荐方法是:

__SFR_OFFSET

如果你真的想使用旧的黑客,请写

setStackPointer:
    ldi r18, lo8(RAMEND)
    out _SFR_IO_ADDR(SPL), r18
    ldi r18, hi8(RAMEND)
    out _SFR_IO_ADDR(SPH), r18
    ret

在您的计划开始时。并注意双重 在宏名称的开头加下划线。