Kra*_*rab 11 x86 assembly cpu-registers memory-segmentation
我需要修改一些DLL,但我不知道,什么excatly确实段寄存器(DS,SS,...)的保护模式.我在学校里学到了真正的16位模式,其中段寄存器在正常寄存器中乘以16加偏移量,在物理存储器中提供有效地址.在保护模式下,有一些平面内存模型和虚拟内存,每个进程"有"4GB内存,所以如果寄存器有32位,那么我只能通过"偏移"寄存器来寻址虚拟内存的每个字节.例如,哪些瞳孔具有保护模式中的段寄存器
mov eax, dword ptr ds:[20037DA0]
Run Code Online (Sandbox Code Playgroud)
基本上,目的与实际模式相同,只是它们的工作方式略有不同.您的示例中的DS在您的GDT中选择一个内存描述符(谷歌这个术语,如果你真的想理解这一点,"全局描述符表"),它包含基地址,结束地址,粒度等信息.然后你的偏移量被添加到基地址, 结束.如果你在windows上(我在linux上打赌它一样),你根本不必担心这些段寄存器,正如你所说的扁平模型,这意味着所有内存应该只有一个描述符,所以如果你不改变这些寄存器应该像它们甚至不存在一样工作.
一些历史背景
8086始终使用每段固定的64KiB窗口,其起始地址由(段寄存器*16)计算.由于80286在内存中有一些特殊的表(GDT和LDT).这些表包含段的起始地址,长度和访问权限.段寄存器(CS,DS,ES,SS - 以及80386:FS,GS)包含这些表的索引.
因此理论上,操作系统可以以它想要的方式设置段的偏移量和长度:在8086 DS = 0x0123意味着:段是从地址0x01230开始的64KiB.在32位模式下,DS = 0x0123可能意味着:段从地址0xABCD开始,长度为0xEF字节 - 这取决于操作系统创建的GDT和LDT表的内容.尝试访问此范围之外的段(如果长度<0x1000,则DS:0x1000)将导致异常(中断).
现在的情况
但是,大多数现代32位操作系统不再使用段寄存器.由于访问权限问题,它们的值是根据模式(内核或用户)设置的.起始地址通常为0,长度为4GiB.
使用MMU完成实际内存保护,以便在用户模式下无法访问某些内存区域.在现代操作系统中,MMU绝对是必不可少的.它将"绝对"虚拟地址映射到检查访问权限违规的真实物理地址.
有一个例外:某些操作系统(例如Windows和Linux)使用FS和/或GS段来指向不同的内存区域.
因此,在64位模式下,x86处理器仅将CS寄存器用于访问权限问题,FS和GS可用于向每个地址添加偏移量.据我所知DS,ES和SS不使用,而寄存器FS和GS的内容无关紧要,但有一些特殊的寄存器明确地将偏移量添加到使用FS或GS的操作中.
| 归档时间: |
|
| 查看次数: |
4503 次 |
| 最近记录: |