asm in C“’mov’的内存引用太多了”
我看过关于同样错误的post,但我仍然得到错误:
too many memory references for `mov' junk `hCPUIDmov buffer' after expression
…这是代码(mingw编译器/ C :: B):
#include iostream using namespace std; union aregister { int theint; unsigned bits[32]; }; union tonibbles { int integer; short parts[2]; }; void GetSerial() { int part1,part2,part3; aregister issupported; int buffer; __asm( "mov %eax, 01h" "CPUID" "mov buffer, edx" );//do the cpuid, move the edx (feature set register) to "buffer" issupported.theint = buffer; if(issupported.bits[18])//it is supported { __asm( "mov part1, eax" "mov %eax, 03h" "CPUID" );//move the first part into "part1" and call cpuid with the next subfunction to get //the next 64 bits __asm( "mov part2, edx" "mov part3, ecx" );//now we have all the 96 bits of the serial number tonibbles serial[3];//to split it up into two nibbles serial[0].integer = part1;//first part serial[1].integer = part2;//second serial[2].integer = part3;//third } }
您的汇编代码未正确格式化为gcc。
首先,gcc使用AT&T语法(编辑: 默认情况下,感谢nrz ),因此它需要为每个寄存器引用添加%
,并为立即操作数添加$
。 目标操作数始终位于右侧 。
其次,您需要为新行传递行分隔符(例如\n\t
)。 由于gcc直接将字符串传递给汇编程序,因此需要特定的语法。
您通常应该尽量减少汇编程序,因为它可能会导致优化程序出现问题。 最小化所需汇编程序的最简单方法可能是将cpuid指令分解为函数,并重用它。
void cpuid(int32_t *peax, int32_t *pebx, int32_t *pecx, int32_t *pedx) { __asm( "CPUID" /* All outputs (eax, ebx, ecx, edx) */ : "=a"(*peax), "=b"(*pebx), "=c"(*pecx), "=d"(*pedx) /* All inputs (eax) */ : "a"(*peax) ); }
然后只需简单地使用;
int a=1, b, c, d; cpuid(&a, &b, &c, &d);
另一种可能更优雅的方法是使用宏来实现 。
-
由于C如何工作,
__asm( "mov %eax, 01h" "CPUID" "mov buffer, edx" );
相当于
__asm("mov %eax, 01h" "CPUID" "mov buffer, edx");
这相当于
__asm("mov %eax, 01hCPUIDmov buffer, edx");
这不是你想要的。
-
AT&T语法(GAS的默认值)将目标寄存器放在最后。
-
AT&T语法要求immediates以$为前缀。
-
你不能像那样引用局部变量; 你需要将它们作为操作数传递。
维基百科的文章给出了一个返回eax的工作示例。
以下代码段可能涵盖您的用例(我不熟悉GCC内联汇编或CPUID):
int eax, ebx, ecx, edx; eax = 1; __asm( "cpuid" : "+a" (eax), "+b" (ebx), "+c" (ecx), "+d" (edx)); buffer = edx