为什么 "Impossible constraint" 使用类型化的 8 位常量而不是等效的 #define?

Why "Impossible constraint" with a typed 8-bit constant but not with an equivalent #define?

我在 AVR 8 位微控制器(如 ATtiny1634 或 ATmega328)的内联汇编代码中使用约束 "M" 标记的 8 位类型常量收到有关使用不可能约束的错误消息:

static const uint8_t tail_mask = (uint8_t)((rx1::queue_length-1) << \
    rx1::queue_length_bits) & 0xFF;

asm(
    ...
    "andi r30, %0\n\t"
    ...
:
: "M" (tail_mask)
);

warning: asm operand 1 probably doesn't match constraints

这里rx1是一个class名字,queue_lengthqueue_length_bits都是static const uint8_tclass常量。我可以用"O""N",没办法。使用 staticint8_t 与否没有区别。

如果我用 #define 替换上面的 static const uint8_t 定义,错误消息就会消失!

#define tail_mask ((rx1::queue_length-1) << rx1::queue_length_bits)

asm(
    ...
    "andi r30, %0\n\t"
    ...
:
: "M" (tail_mask)
);

编译正常!

这让我很烦恼。为什么使用强制的 8 位无符号常量会在强制其成为... 8 位无符号常量的约束上产生错误消息?

郑重声明,我使用的是 avr-gcc 版本 7.1.0.

传递给约束的值在这里应该是一个32位整数。当你使用 #define 时你会得到什么,因为它被静默地提升为预期的类型。同样,使用 int 或 unsigned 作为 tail_mask 值也可以。奇怪的是我经历了 documentation 的几个版本,但没有发现 M 约束参数不能是 uint8_t 或类似的证据。