linux 0.11的地址翻译(地址映射)过程

        首先以汇编级调试的方式启动bochs,引导Linux 0.11,在0.11下编译和运行test.c。它是个无限循环的程序,永远不会主动退出。然后在调试器中动过查看各项系统参数,从逻辑地址,LDT表,GDT表,线性地址到页表,计算出变量i的物理地址。最后通过直接修改物理内存的方式让test.c退出运行,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后,首先通过运行./dbg-asm启动调试器,此时Bochs的窗口处于黑屏状态,而命令行窗口显示:

========================================================================
                       Bochs x86 Emulator 2.3.7
               Build from CVS snapshot, on June 3, 2008
========================================================================
00000000000i[     ] reading configuration from ./bochs/bochsrc.bxrc
00000000000i[     ] installing x module as the Bochs GUI
00000000000i[     ] using log file ./bochsout.txt
Next at t=0
(0) [0xfffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b         ; ea5be000f0
<bochs:1>_

"Next at t=0"表示下面的指令是Bochs启动后要执行的第一条软件指令。单步跟踪进去就能看见BIOS的代码。不过这不是本实验需要的。直接输入命令"c",continue程序的运行,Bochs一如既往地启动了Linux 0.11。

在Linux 0.11下输入test.c,编译test,运行之,打印如下信息:

The logical/virtual address of i is 0x00003004

只要test不变,0x00003004这个值在任何人的机器上都是一样的。即使在同一个机器上多次运行test,也是一样的。test是一个死循环,只会不停占用CPU,不会退出。

暂停

当test运行的时候,在命令行窗口按“ctrl+c”,Bochs会暂停运行,进入调试状态。绝大多数情况下都会停在test内,显示类似如下信息:

(0) [0x00fc8031] 000f:00000031 (unk. ctxt): cmp dword ptr ds:0x3004, 0x00000000 ; 833d0430000000

其中加粗的“000f”如果是0008,则说明中断在了内核里。那么就要c,然后在ctrl+c,直到变为"000f"为止。如果显示的下一条指令不是"cmp ...",就用"n"命令单步运行几步,直到停在"cmp ..."。

使用命令"u /7",显示从当前位置开始7条指令的反汇编代码,如下:

0000031: (                    ): cmp dword ptr ds:0x3004, 0x00000000 ; 833d0430000000
10000038: (                    ): jz .+0x00000002           ; 7402
1000003a: (                    ): jmp .+0xfffffff5          ; ebf5
1000003c: (                    ): xor eax, eax              ; 31c0
1000003e: (                    ): jmp .+0x00000000          ; eb00
10000040: (                    ): leave                     ; c9
10000041: (                    ): ret                       ; c3

这就是test.c中从while开始一直到return的汇编代码。变量i保存在ds:0x3004这个地址,并不停地和0进行比较,直到它为0,才会跳出循环。

现在,开始寻找ds:0x3004对应的物理地址。

段表

ds:0x3004是虚拟地址,ds表明这个地址属于ds段。首先要找到段表,然后通过ds的值在段表中找到ds段的具体信息,才能继续进行地址翻译。每个在IA-32上运行的应用程序都有一个段表,叫LDT,段的信息叫段描述符。

LDT在哪里呢?ldtr寄存器时线索的起点,通过它可以在GDT(全局描述符表)中找到LDT的物理地址。

用"sreg"命令:

cs:s=0x000f, dl=0x00000002, dh=0x10c0fa00, valid=1
ds:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=3
ss:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
es:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
fs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
gs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
ldtr:s=0x0068, dl=0xc2d00068, dh=0x000082f9, valid=1
tr:s=0x0060, dl=0x52e80068, dh=0x00008bfd, valid=1
gdtr:base=0x00005cc8, limit=0x7ff
idtr:base=0x000054c8, limit=0x7ff

可以看到看到ldtr的值是0x0068=0000000001101000(二进制),表示LDT表存放在GDT表的1101(二进制)=13(十进制)号位置(每位数据的意义参考后文描述的段选择子)。而GDT的位置已经由gdtr明确给出,在物理地址的0x00005cc8。用“xp /32w 0x00005cc8”查看该地址开始,32个字的内容,及GDT表的前16项。如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值