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