转自:点击打开链接
在实模式下不受 1M 空间限制访问 4G 空间,实现这个目的仅仅需要一点小“技俩”,这就是某些资料上所说的 big mode
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 却出现故障启动不了。
没在真实环境试过。