Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 在x86 32位中禁用分页_Assembly_X86_Paging_Virtual Memory_Page Fault - Fatal编程技术网

Assembly 在x86 32位中禁用分页

Assembly 在x86 32位中禁用分页,assembly,x86,paging,virtual-memory,page-fault,Assembly,X86,Paging,Virtual Memory,Page Fault,我试图直接写入物理内存位置,因此我使用汇编函数首先禁用分页,写入值,然后重新启用分页,但由于某些原因,在尝试写入值时仍会触发页面错误 据我所知,在x86-32位中,分页是通过在cr0中翻转位32来设置的,因此下面是我的汇编函数: mov 4(%esp), %ecx //address mov 8(%esp), %edx //value mov %cr0, %eax and $0x7fffffff, %eax mov %eax, %cr0 mov %edx, (%ecx) //this lin

我试图直接写入物理内存位置,因此我使用汇编函数首先禁用分页,写入值,然后重新启用分页,但由于某些原因,在尝试写入值时仍会触发页面错误

据我所知,在x86-32位中,分页是通过在cr0中翻转位32来设置的,因此下面是我的汇编函数:

mov 4(%esp), %ecx //address
mov 8(%esp), %edx //value

mov %cr0, %eax
and $0x7fffffff, %eax
mov %eax, %cr0

mov %edx, (%ecx) //this line still triggers a page fault somehow

or $0x80000000, %eax
mov %eax, %cr0

ret

这是实现我想做的事情的正确方法吗?如果是这样,为什么在cr0中的位翻转时仍会触发页面错误?

当跳转指令(仅限远跳转)完成时,cr0寄存器中的更改将变为活动状态

但是,禁用分页不是一个好主意:您必须保证代码位于1:1映射内存中,并且中断被禁用

如果使用堆栈,还必须确保堆栈映射为1:1

通过将ecx中的物理地址映射到虚拟地址,然后写入虚拟地址的方式修改页表要容易得多。

描述了如何禁用分页,作为从保护模式切换回实模式过程的一部分:

9.9.2切换回实地址模式 处理器从保护模式切换回实地址模式 如果软件清除CR0中的PE位 使用MOV CR0指令注册。重新进入的程序 实地址模式应执行以下步骤:

  • 禁用中断。CLI指令禁用可屏蔽硬件中断。可以使用外部电路禁用NMI中断
  • 如果已启用分页,请执行以下操作:

    • 将程序控制转移到标识映射到物理地址(即线性地址)的线性地址 地址等于物理地址)
    • 确保GDT和IDT位于标识映射页面中
    • 清除CR0寄存器中的PG位
    • 将0H移入CR3寄存器以刷新TLB
  • 看来你错过了最后一步。TLB(翻译查找缓冲区)是CPU缓存页表条目的地方,清除PG位后仍处于活动状态。您需要清除TLB,否则CPU将继续使用它


    请注意,在再次设置PG位之前,必须重新加载CR3。另外,因为您所做的是非常不寻常的,您可能会遇到错误和兼容性问题与您的模拟器。在切换回实模式的过程中,它可能只能正确地处理禁用分页的问题,因为这可能是它被测试的唯一场景。甚至物理CPU在这方面也可能有问题。

    您是否试图在已启用分页的操作系统上禁用分页?它是您自己的操作系统还是众所周知的操作系统(linux、Windows、MacOS)?当现代操作系统已经启用分页功能时,绝对不应该禁用它。要写入物理地址,可以使用操作系统提供的工具(
    /dev/mem
    设备\PhysicalMemory
    )或kernel.BTW提供的函数(我不习惯AT&T语法)您在代码中反转了一个地址的值。实际上这是第31位,因为第0位是第一位。如果代码从具有不同物理地址和虚拟地址的页面运行,禁用分页不会导致错误吗?或者更确切地说,既然
    EIP
    是一个物理地址,就让其他指令运行。你有没有在
    bochs
    中单步执行此操作,或者在发生故障时查看到底发生了什么?此外,我认为明智的方法是将物理页映射到某个虚拟内存中,然后写入它。不过,这是一种无聊的方式。这种疯狂的方式看起来确实很有趣。如果代码、堆栈、GDT、IDT、所有中断处理程序以及它们可能使用的所有东西都是标识映射的,那么禁用和重新启用分页将是“安全的”;但是它也会很慢(使所有TLB条目无效),并且您必须想一想,如果所有内容都是标识映射的,那么您为什么要首先启用分页功能呢