'asm'中不可能的约束:__asm__ __volatile__ [英] Impossible constraint in 'asm': __asm__ __volatile__

查看:539
本文介绍了'asm'中不可能的约束:__asm__ __volatile__的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几天以来,我试图编写一个非常简单的内联汇编代码,但没有任何效果。我有IDE NetBeans和编译器MinGW。
我的最新代码是:

I trying since a few days to write a very simple inline assembler code, but nothing worked. I have as IDE NetBeans and as compiler MinGW. My latest code is:

uint16 readle_uint16(const uint8 * buffer, int offset) {
    unsigned char x, y, z;
    unsigned int PORTB;
    __asm__ __volatile__("\n"
        "addl r29,%0\n"
        "addl r30,%1\n"
        "addl r31,%2\n"
        "lpm\n"
        "out %3,r0\n"
        : "=I" (PORTB)
        : "r" (x), "r" (y), "r" (z)
    );
    return value;
}

但是我每次都收到相同的消息错误:'asm'中的不可能约束。
我试图将所有内容写在一行中,或者使用其他 asm 简介。我不知道该怎么办。

But I get everytime the same message "error: impossible constraint in 'asm'". I tried to write all in a single line or to use different asm introductions. I have no idea what I can do otherwise.

推荐答案

请注意,gcc的内联汇编语法为

Notice that gcc's inline assembly syntax is

asm [volatile] ( AssemblerTemplate
                      : OutputOperands
                      [ : InputOperands
                      [ : Clobbers ] ])

在汇编程序指令之后,首先输入输出操作数,然后输入。

After the assembler instructions first come the output operands, then the inputs.

正如@DavidWohlferd所说, I 用于常量大于-1,小于64个 常量(立即数)。

As @DavidWohlferd said, I is for "constant greater than −1, less than 64 "constants ("immediates").

虽然 out 指令实际上需要该范围内的恒定值,但 PORTB not 该常数值。 (如果您查看控制器的相应 avr / ioXXXX.h 文件,则可以自己看到,在其中您可能会找到类似 #define的文件PORTB _SFR_IO8(0x05)。)

While the out instruction in fact requires a constant value from that range, PORTB is not that constant value. (You can see that for yourself if you look into the corresponding avr/ioXXXX.h file for your controller, where you may find something like #define PORTB _SFR_IO8(0x05).)

此外,并非所有IO寄存器都可以通过 out / in ;特别是较大的控制器具有64个以上的IO寄存器,但只能访问前64个IO寄存器。但是,可以通过 lds / sts 在其内存映射地址访问所有IO寄存器。因此,根据您要访问哪个控制器的哪个寄存器,您可能根本无法使用 out 对该寄存器进行操作,但是始终可以使用 sts 。如果您希望代码具有可移植性,则必须考虑到这一点,例如建议的

Also, not all IO registers may be accessible via out/in; especially the bigger controllers have more than 64 IO registers, but only the first 64 can be accessed as such. However, all IO registers can be accessed at their memory-mapped address through lds/sts. So, depending on which register on which controller you want to access you may not be able to use out for that register at all, but you can always use sts instead. If you want your code to be portable you'll have to take that into account, like suggested here for example.

如果您知道 PORTB 是前64个之一IO在控制器上注册,您可以将

If you know that PORTB is one of the first 64 IO registers on your controller, you can use

I(_SFR_IO_ADDR(PORTB))与<$ c一起使用$ c> out ,否则将

m(PORTB) sts

因此,这是:

__asm__ __volatile__("\n"
    "addl r29,%0\n"
    "addl r30,%1\n"
    "addl r31,%2\n"
    "lpm\n"
    "out %3,r0\n"
    : /* No output operands here */
    : "r" (x), "r" (y), "r" (z), "I" (_SFR_IO_ADDR( PORTB ))

);

应该使您摆脱不可能的约束错误。尽管代码仍然没有任何意义,主要是因为您使用的是随机未初始化的数据作为输入。您在不声明r29-r31的情况下对其进行了注册,而且我完全不确定 lpm 之前的所有代码的意图。

should get you rid of that "impossible constraint" error. Although the code still does not make any sense, mostly because you're using "random", uninitialized data as input. You clobber registers r29-r31 without declaring them, and I'm totally not sure what your intention is with all the code before the lpm.

这篇关于'asm'中不可能的约束:__asm__ __volatile__的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆