环境:Debian 9.5-gcc 6.3.0
当我尝试使用多个InputOperands
时,无法使用嵌入式程序集功能。
我正在使用以下代码(基本rol
函数,1 InputOperand
,预定义rol
操作数):
#include <stdio.h>
#include <stdlib.h>
void asm_rol(int32_t* p_rolled)
{
__asm__ volatile
(
".intel_syntax noprefix;"
"rol %0, 1;"
:"=a"(*p_rolled)
:"a"(*p_rolled)
:"cc"
);
}
int main(int argc, char** argv)
{
int32_t test = 0x1;
asm_rol(&test);
printf("0x%08x\n", test);
return 0;
}
这将打印0x00000002
,并且是rol 0x1, 1
的正确结果。
现在,我不明白为什么以下代码无法编译。我认为我对InputOperands
的使用是不好的:
#include <stdio.h>
#include <stdlib.h>
void asm_rol(int32_t* p_rolled, int16_t i)
{
__asm__ volatile
(
".intel_syntax noprefix;"
"rol %0, %1;"
:"=a"(*p_rolled)
:"a"(*p_rolled), "b"(i)
:"cc"
);
}
int main(int argc, char** argv)
{
int32_t test = 0x1;
asm_rol(&test, 1);
printf("0x%08x\n", test);
return 0;
}
gcc返回错误:
resolve.c: Assembler messages:
resolve.c:6: Error: operand type mismatch for `rol'
我尝试将int8_t
的{{1}}和int32_t
用于i
,它没有任何改变。
我必须说,在这种环境下,我是C嵌入式AS的新手,我只使用Windows上的Visual Studio完成了一些基本的内联汇编。
答案 0 :(得分:3)
如Michael Petch在评论中所说,
控制移位位数的移位指令唯一允许的寄存器是CL
他还提供了以下解决方案:
void asm_rol(int32_t* p_rolled, int8_t i) { __asm__ volatile ( ".intel_syntax noprefix;" "rol %0, %1;" :"+a"(*p_rolled) :"cI"(i) :"cc" ); }
c表示要使用CL寄存器(假设您将变量i的类型更改为int8_t而不是int16_t。Capital-Eye(I)说约束也可以是0到32之间的立即值。
正如Michael Petch和Peter Cordes在评论中指出的那样,我的代码无法正常工作,因为我使用%1
作为rol
操作数,但是正确的变量是%2
。我犯了这个错误,是因为我认为InputOperands
仅引用了%#
。
Michael Petch和Peter Cordes还提供了一些不错的文档:
(...)机器约束可以在这里找到:i386信息下的gcc.gnu.org/onlinedocs/gcc/…
没有理由使用内联汇编进行旋转。 Best practices for circular shift (rotate) operations in C++
调试嵌入式asm时,应查看由编译器生成的asm,以查看将其替换为模板的内容。例如godbolt.org很方便:How to remove "noise" from GCC/clang assembly output?。您甚至可以执行诸如nop#%0%1%2之类的操作,以查看编译器为所有操作数选择的内容,无论是否在模板中引用它们。另请参见stackoverflow.com/tags/inline-assembly/info,以获取更多指南和示例。