需要帮助将定义的C常量传递给asm指令



我在ATmega微控制器的C程序中有以下代码:

define sbi(port,bit) asm("SBI " #port "," #bit)
[...]
sbi(PORTB,1);

问题是编译器在处理程序集代码时无法识别PORTB,尽管它是在包含的头文件中定义的。有没有一种方法可以告诉预编译器将定义的PORTB(0x1b(值放在ASM指令中,而不是文本PORTB?当我手动这样做时,组装说明工作正常:

sbi(0x1b,1);

但出于显而易见的原因,我希望能够在C代码中使用PORTB和其他定义的名称。

请注意,我只将这个ASM宏用于定义的常量,而不是变量,所以我不需要任何太花哨的东西来桥接我的ASM宏和C代码。我只需要预处理器将ASM字符串中的PORTB替换为0x1b。

通常不应使用字符串化(宏#运算符(为asm构造构造字符串。相反,请使用扩展的asm语法。

要将操作数放入汇编指令中,请将该语法与约束一起使用,这些约束告诉编译器如何将操作数提供给指令。对于立即数操作数,请使用i:

asm("SBI %[port], %[bit]"
: // Output operands would be here.
: // Input operands are here.
[port] "i" (PORT),
[bit]  "i" (1)
);

指令字符串中的%[port]将替换为名为port的操作数。稍后操作数列表中的[port]表示该操作数的名称为port。当然,除了大小写之外,这与PORT匹配,但您可以使用其他名称。

"i"表示要使用立即数操作数,该操作数必须具有编译时常数值。

(PORT)中的PORT是一个表达式,用于给出操作数的值。例如,您也可以使用(PORT+1)

1操作数可以是硬编码的,但上面展示了如何保持它的灵活性。

对于具有i的默认立即数操作数,GCC和Clang包括在汇编代码中标记立即数操作的标点符号,例如某些汇编程序中的$。如果由于某种原因这是一个问题,可以使用%c[port]而不是%[port]来获得裸操作数,并手动插入#,如:

asm("SBI #%c[port], #%c[bit]"
: // Output operands would be here.
: // Input operands are here.
[port] "i" (PORT),
[bit]  "i" (1)
);

最新更新