- 论坛徽章:
- 0
|
话题 2 : 实模式下访问 4G 地址空间
在之前我的文档中几次提到在实模式下不受 1M 空间限制访问 4G 空间。
实现这个目的仅仅需要一点小“技俩”
2.1 原理
real mode -> protected mode -> real mode
在实模式转化为 protected 模式时,设置好该问 4G 空间的 descriptors,加载进相应的的 selector,而转回 real 模式时,却不改变相应的 selector。
2.2 实现
下面是相应的汇编码片断示例:
cli
lgdt gdt32
mov eax, cr0
or eax, 0x1
mov cr0, eax /* 开启 protected mode */
jmp code32 /* jmp to code32 */
code32:
mov bx, 0x18
mov ds, bx
mov ss, bx
xor eax, 0x01
mov cr0, eax /* 回到 real mode */
jmp code16
code16:
mov eax, 0x11223344
mov dword ptr [eax], 0x12345678 /* 关键代码:real 下写 1M 以上空间代码 */
looo:
jmp looo /* 死循环 */
|
开启 protected mode 时,将 32 位的 descriptor 加载到 segment registers 形成 protected 模式执行环境,返回 real 模式却没变回 real 模式的执行环境,仍旧是 protected 模式执行环境。
以下是示例中的 descriptors table:
0x00000000
0x00000000 /* gdt0: null descriptor */
0x0000ffff
0x00cf9e00 /* gdt1: 32 bit code descriptor */
0x0000ffff
0x00009e00 /* gdt2: 16 bit code descriptor */
0x0000ffff
0x00cf9300 /* gdt3: 32 bit data descriptor */
0x0000ffff
0x00009300 /* gdt4: 16 bit data descriptor */
|
示例中只用了 gdt1 及 gdt3
2.3 实验
00007c00: fa ; cli
00007c01: 0f 01 16 f0 7c ; lgdt [0x7cf0]
00007c06: 66 0f 20 c0 ; mov eax, cr0
00007c0a: 80 c8 01 ; or al, 0x01
00007c0d: 66 0f 22 c0 ; mov cr0, eax
00007c11: ea 16 7c 00 08 ; jmp far 0008:7c16
00007c16: c6 c3 18 ; mov bl, 0x18
00007c19: 8e db ; mov ds, bx
00007c1b: 8e d3 ; mov ss, bx
00007c1d: 80 f0 01 ; xor al, 0x01
00007c20: 66 0f 22 c0 ; mov cr0, eax
00007c24: eb 00 ; jmp $+00
00007c26: b8 44 33 22 11 ; mov eax, 0x11223344
00007c2b: c7 00 78 56 34 12 ; mov dword ptr [eax], 0x12345678
00007c31: eb fe ; jmp .
|
上面这段机器码是我手工翻译的,懒得使用 nasm,而对 nasm 反感,所以就亲自动手了 
将它复制到 floppy 映像的 boot 块。
bios 会将 floppy bootsect 加载了 0x7c00 处执行......
然后,使用 bochs 用 floppy 启动。
附上完整的 a.img (可启动的软盘映像)
2.4 结果
在 bochs 启动 a.img 是死循环这是正常的,因为程序中结果是死循环。
用 vmware 加载 floppy 却出现故障启动不了。
没在真实环境试过。
[ 本帖最后由 mik 于 2008-12-24 00:44 编辑 ] |
|