C程序获取逻辑地址对应物理地址报unsupported instruction `mov'错误求助
这个报错的核心原因是你写的32位x86内联汇编不兼容64位编译环境:64位架构下CR0/CR3/CR4均为64位寄存器,无法直接写入32位的eax寄存器,同时你用unsigned int存储CR寄存器值也会出现高位截断。
优先使用Linux内核已经封装好的CR寄存器读取接口,不需要自行编写内联汇编,兼容性更强,修改后的代码如下:
// 需新增头文件引入CR寄存器读取接口 #include <asm/processor.h> static int my_seq_show(struct seq_file *m, void *p) { // 变量类型改为unsigned long适配64位寄存器长度 unsigned long _cr0,_cr3, _cr4; get_pgtable_macro(m); printk("the get_pgtable_macro has been output\n"); if (indata.p !=0 && indata.addr !=0) vaddr2paddr(m, indata.addr,indata.p); printk("the vaddr2paddr has been done\n"); // 替换原有内联汇编为内核原生接口,自动适配32/64位环境 _cr0 = read_cr0(); _cr3 = read_cr3(); _cr4 = read_cr4(); // 打印格式符调整为%016lX适配64位值输出 seq_printf(m, " CR0=0x%016lX", _cr0 ); seq_printf(m, " CR3=0x%016lX", _cr3 ); seq_printf(m, " CR4=0x%016lX", _cr4 ); seq_printf(m, " PE=%lX", (_cr0 >> 1)&1 ); seq_printf(m, " PG=%lX", (_cr0 >> 31)&1 ); seq_printf(m, " PAE=%lX", (_cr4 >> 5)&1 ); seq_printf(m, " PSE=%lX", (_cr4 >> 4)&1 ); seq_printf( m, "\n" ); return 0; }
如果确实需要自行编写内联汇编实现,64位环境下的写法参考如下:
asm("mov %%cr0, %%rax\n mov %%rax, %0" : "=m" (_cr0) :: "rax"); asm("mov %%cr3, %%rax\n mov %%rax, %0" : "=m" (_cr3) :: "rax"); asm("mov %%cr4, %%rax\n mov %%rax, %0" : "=m" (_cr4) :: "rax");
仍需搭配unsigned long类型的变量使用,否则还是会出现值截断问题,更推荐使用内核原生接口。
内容的提问来源于stack exchange,提问作者Su.
相关产品推荐
相关产品推荐

