【发布时间】:2019-01-18 14:57:42
【问题描述】:
我正在尝试创建的是用于调用 BTSTS 指令的 c 高级方法。
到目前为止我尝试了什么:
volatile unsigned int a = 1;
asm volatile(
"btsts %0, #2\n"
: "+d" (b)
:
: "cc"
);
以上产生以下汇编输出:
mov #1,w0
mov w0,[w14]
mov [w14],w0
mov w0,w1
btsts w1, #2
mov w1,w0
mov w0,[w14]
但这不是我想要的。该位应直接在内存中设置,以便指令是原子的:
btsts [w0], #2
实现它的正确方法是什么?
最近的方法如下:
这里的“a”是全局变量而不是局部变量
asm volatile(
"btsts [%0], #2\n"
:
: "d" (&a)
: "cc"
);
这次生成如下汇编输出:
mov _a,w0
mov w0,w1
btsts [w1], #2
它好一点,但是我不想明确指定它周围的大括号 [%0]。 编译器/汇编器没有办法知道需要间接内存寻址吗?
编辑:我又尝试了一件事。尽管文档中没有提到“m”约束,但我尝试了它
volatile unsigned int r = 0;
void test(volatile unsigned int* t) {
asm (
"btsts %0, #2\n"
: "+m" (t)
);
}
上面会产生类似的东西
mov #_r,w0
...
mov w0,[w14]
btsts [w14], #2
这也是不正确的,不会改变r。也许没有提到“m”约束是因为它有问题?
顺便说一句。正确的代码是
btsts [w0], #2
或类似的东西
mov w0,[w14]
mov [w14],w1
btsts [w1], #2
【问题讨论】:
-
您的第一个示例显示
"+d" (b),但没有名为b的变量(您的意思是a?)。我不熟悉 xc16,但如果这是 gcc,我会使用+m而不是+d。 xc16 不支持这个约束吗? -
关于表 1-16 MPLAB XC16 编译器用户指南,除了“d”、“g”和其他一些约束之外,没有“m”约束。
-
你试过“+m”吗?如果这个编译器是基于 gcc 的,它可能仍然可以工作。也许文档有误?
-
是的,我试过“+m”。编译器产生了一些东西,但不幸的是产生了无效的指令。
-
因此,查看程序员参考手册(其中定义了 xc16 的指令集),
btsts.c指令似乎不支持将内存地址作为参数,仅支持寄存器(实际上,我认为他们的任何指示都不支持这一点)。指令集的细节因处理器而异(你没有指定你的)所以ymmv,但我猜这是整个芯片组固有的。
标签: c memory inline-assembly xc16