操作系统实验报告-地址映射

地址映射

实验步骤

用汇编级调试启动linux-0.11:

cd ~/workspace/oslab
./dbg-asm

ubuntu终端进入bochs的调试模式,先让linux-0.11正常运行:

在linux-0.11中添加文件/usr/root/test.c,内容如下:

#include <stdio.h>

int i = 0x12345678;

int main(void)
{
    printf("The logical/virtual address of i is 0x%08x", &i);
    fflush(stdout);

    while (i)
        ;

    return 0;
}

在linux-0.11中编译test.c,运行目标文件:

gcc -o test test.c
./test

程序进入死循环,切换到ubuntu的终端,按下Ctrl+C暂停linux-0.11:

为了让linux-0.11中运行的test跳出循环,需要找到逻辑地址ds:0x3004对应的物理地址,将其内容(变量i)改为0。

首先要得到段表LDT,取得ds对应的段描述符,才能得到ds的基址,从而得到ds:0x3004对应的线性地址,进而从线性地址计算出物理地址。

LDT的段描述符

段描述符放在LDT中,ldt的描述符放在GDT中,GDT的地址与LDT在GDT中的项的索引分别保存在gdtr和ldtr中:

s部分是一个段选择子,dl和dh是bochs自动算得的段描述符。

ldtr为0x0068 => 0000 0000 0110 1000 b,可知索引为1101b即13,TI位为0,即GDT中的第13项为LDT的段描述符,每个段描述符64bit => 8byte:

得到的LDT段描述符(与sreg指令得到的ldtr中的dl、dh相同),从而我们可以得到LDT的基址为0x00f9a2d0。

ds的段描述符

ds段选择子为0x0017 => 0000 0000 0001 0111 b,可知索引为10b即2,TI位为1,即LDT中的第2项为ds的段描述符,每个段描述符64bit => 8byte:

得到的ds段描述符,从而我们可以得到ds的基址为0x10000000。

线性地址

故ds:0x3004对应的线性地址为0x10000000+0x3004=0x10003004。

由线性地址计算出物理地址 

线性地址0x10003004 => 0001 0000 0000 0000 0011 0000 0000 0100 b,可知页目录号为1000000b即64,页表为11b即3,页内偏移为100b即4 。

页目录表的基址存放于CR3中:

获取页目录项:

可知页表基地址为0x00fa9000 。

获取页表项:

可知物理页基地址为0x00fa7000 。

可以看到内容是test.c中的变量i的值,将它设置为0:

让linux-0.11继续运行:

成功跳出循环,程序结束:

注解

段选择子

RPL:特权级,0~3权限递减;

TI:1表示INDEX为LDT表中的索引,0表示为GDT的;

INDEX:段描述符在表(LDT/GDT)中的项的索引。

段描述符中的段基址

段基址在段描述符中被分成3个部分,重新组合即可得到段基址。

由线性地址计算出物理地址

directory:页目录号

table:页表号

offset:页内偏移

table_base/page_base:页目录项/页表项的物理页面框号,作为地址的高位(其值左移12位得到基址)

原文地址:https://www.cnblogs.com/tradoff/p/5774355.html