GCC内联汇编如何将cpuid寄存器值直接映射到char数组无需显式mov
问题原因分析
1. 仅输出单个字符的原因
你最初写的"=b"(*vendor)中,*vendor的类型是char,仅占1字节。此时内联汇编只会将ebx寄存器的低8位赋值给vendor[0],所以最终只能输出第一个字符G,剩下的3个字节没有被写入数组。
2. 强转报错的原因
你尝试的"=b"((uint32_t*) vendor)写法中,(uint32_t*) vendor是一个指针右值,不是可被赋值的左值,而内联汇编的输出操作数要求必须是可修改的左值,因此编译会抛出invalid lvalue in asm output错误。
正确实现方案
你最终补充的写法就是不需要显式mov指令的标准实现:
asm volatile( "cpuid\n" :"=b"(*(uint32_t*)vendor),"=d"(*(uint32_t*)(vendor+4)),"=c"(*(uint32_t*)(vendor+8)) :"a"(leaf) : );
这种写法的原理是:将char*类型的数组指针强转为uint32_t*后再解引用,得到的是一个4字节宽度的左值,刚好匹配32位寄存器的位宽。使用=b、=d、=c寄存器约束分别绑定ebx、edx、ecx后,编译器会自动生成将寄存器值写入对应内存地址的代码,不需要你手动在汇编块中编写mov指令,同时也能保证4字节数据完整写入数组的对应位置。
相比你在Block1中手动写mov的实现,这种方案让编译器负责寄存器到内存的赋值,还可以配合编译器的优化策略做指令调度,执行效率更高。
内容的提问来源于stack exchange,提问作者prism1729
相关产品推荐
相关产品推荐

