X86 如何从程序访问控制寄存器cr0、cr2、cr3?获取分段错误
我已经写了一个程序,试图读取和写入控制寄存器 程序编译得很好,但当内联程序集即将执行时,它会产生分段错误 代码:X86 如何从程序访问控制寄存器cr0、cr2、cr3?获取分段错误,x86,inline-assembly,cpu-registers,X86,Inline Assembly,Cpu Registers,我已经写了一个程序,试图读取和写入控制寄存器 程序编译得很好,但当内联程序集即将执行时,它会产生分段错误 代码: void指令(int-val) { int i; int值; 对于(i=0;i
void指令(int-val)
{
int i;
int值;
对于(i=0;i
我使用了GDB并逐步检查了每一条装配线,正是在mov%cr0,%eax
上发生了分段故障
有谁知道出了什么问题吗?在控制寄存器之间来回移动时引用:
仅当当前权限级别为0时,才能执行此指令
这意味着指令只能在内核模式下执行
记录cr0、cr2和cr3内容的最小内核模块可能如下所示(32位代码路径未测试):
@卷尾猴六四事件法轮功纳米比亚威视 你知道这个问题已经4岁了吗?自2011年以来,克里斯就再也没有露面过。@DavidWohlferd,我见过。也许有一天他会回来。我不是在等他回答。这样的问题永远有用。我经常回答这些问题,有时还得到代表:-)你的意思是
u64
?“英特尔64位手册”中至少记录了cr3
,从0:63位开始。@corny:这只是一个简单的示例,说明了如何访问控制寄存器,因此为了简单起见,即使在64位模式下,我也只打印较低的32位。我认为所有的控制寄存器在长模式下都是64位的,如果你真的对内容做了一些有用的事情,你肯定需要CR2/CR3的所有位。正确的,在64位模式下,所有的控制寄存器都是64位的。《英特尔64和IA-32体系结构软件开发人员手册》第3A卷第2.5节“控制寄存器”。我编辑了你的答案,让我们删除我们的评论,只保留你改进的答案。我目前没有办法轻松检查代码,但我认为格式字符串应该是64位模式下的%016lx
(或者如果cr0/cr2/cr3被强制转换为无效*
,可以使用%p
)由于它是一个64位寄存器,所以它应该是%016llx(额外长)。
void instructions(int val)
{
int i;
int value;
for(i = 0; i < val; i++)
__asm__("mov %cr0, %eax");
}
/* hello.c */
#include <linux/module.h>
#include <linux/kernel.h>
int init_module(void)
{
#ifdef __x86_64__
u64 cr0, cr2, cr3;
__asm__ __volatile__ (
"mov %%cr0, %%rax\n\t"
"mov %%eax, %0\n\t"
"mov %%cr2, %%rax\n\t"
"mov %%eax, %1\n\t"
"mov %%cr3, %%rax\n\t"
"mov %%eax, %2\n\t"
: "=m" (cr0), "=m" (cr2), "=m" (cr3)
: /* no input */
: "%rax"
);
#elif defined(__i386__)
u32 cr0, cr2, cr3;
__asm__ __volatile__ (
"mov %%cr0, %%eax\n\t"
"mov %%eax, %0\n\t"
"mov %%cr2, %%eax\n\t"
"mov %%eax, %1\n\t"
"mov %%cr3, %%eax\n\t"
"mov %%eax, %2\n\t"
: "=m" (cr0), "=m" (cr2), "=m" (cr3)
: /* no input */
: "%eax"
);
#endif
printk(KERN_INFO "cr0 = 0x%8.8X\n", cr0);
printk(KERN_INFO "cr2 = 0x%8.8X\n", cr2);
printk(KERN_INFO "cr3 = 0x%8.8X\n", cr3);
return 0;
}
void cleanup_module(void)
{
}
# Makefile
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
test: all
sudo insmod ./hello.ko
sudo rmmod hello
dmesg | tail