查看“Unreal Mode”的源代码
←
Unreal Mode
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
'''Unreal mode(“非实模式)'''包括通过调整[[Descriptor Cache|描述符缓存]]来打破实模式段的64KiB限制(同时保留16位指令和<tt>段*16+偏移量<tt>寻址模式)。 ==用途== 非实模式通常在以下两种情况下被推荐使用: * 你正在尝试扩展传统的16位DOS程序,以便它可以处理更大的数据,[[Virtual 8086 Mode]]和xms都不适合你的需要。 * 你正在尝试加载将在大于640K的32位模式下运行的程序(因此你不能将其加载到常规内存中),并且你还不想费心编写保护模式磁盘驱动程序,但你也希望避免在实模式和保护模式之间切换,以将块从传统内存缓冲区复制到扩展内存中。 如果你没有启用 [[A20 Line]],你仍然无法完全访问所有物理RAM; 所有 “奇数” 1 MiB块将不可用。 ==实现== 为此,你需要将段寄存器的描述符缓存限制设置为大于64KiB的任何值(通常为完整的4GiB(<tt>0xffffffff</tt>))。 在保护模式下,段寄存器中的位3-15表示[[GDT|全局描述符表]]的索引。 这就是为什么在下面的代码0x08=1000b中,会得到条目#1(条目#0总是一个空描述符)。 当(在保护模式下)段寄存器被加载了“选择器”时,“段描述符缓存寄存器”被填入描述符值,包括大小Size(或限制limit)。 切换回实模式后,无论16位段寄存器中的值是什么,这些值都不会被修改。 因此,64KiB限制不再有效,32位偏移量可以在实模式下用于实际访问64KiB以上的区域(<tt>段*16 + 32位偏移量</tt>)。 ====大非实模式(Big Unreal Mode)=== 这不会触及CS。 <br /> 因此,IP不受所有这些影响,代码本身仍被限制在64KiB。 <source lang="asm"> ; 汇编示例 ; nasm boot.asm -o boot.bin ; partcopy boot.bin 0 200 -f0 [ORG 0x7c00] ; add to offsets start: xor ax, ax ; make it zero mov ds, ax ; DS=0 mov ss, ax ; stack starts at seg 0 mov sp, 0x9c00 ; 2000h past code start, ; making the stack 7.5k in size cli ; no interrupts push ds ; save real mode lgdt [gdtinfo] ; load gdt register mov eax, cr0 ; switch to pmode by or al,1 ; set pmode bit mov cr0, eax jmp $+2 ; tell 386/486 to not crash mov bx, 0x08 ; select descriptor 1 mov ds, bx ; 8h = 1000b and al,0xFE ; back to realmode mov cr0, eax ; by toggling bit again pop ds ; get back old segment sti mov bx, 0x0f01 ; attrib/char of smiley mov eax, 0x0b8000 ; note 32 bit offset mov word [ds:eax], bx jmp $ ; loop forever gdtinfo: dw gdt_end - gdt - 1 ;last byte in table dd gdt ;start of table gdt dd 0,0 ; entry 0 is always unused flatdesc db 0xff, 0xff, 0, 0, 0, 10010010b, 11001111b, 0 gdt_end: times 510-($-$$) db 0 ; fill sector w/ 0's dw 0xAA55 ; Required by some BIOSes </source> * At least on the 486SL the jmp $+2 instruction is needed after toggling the PM bit off, not just on. - BASICFreak === 巨非实模式(Huge Unreal Mode) === 巨非实模式使代码超过64KiB。 然而,由于实模式中断不会自动保存EIP的高16位,因此实现起来更加困难。 初始化很简单,你只需加载一个4GiB限制的代码段: <source lang="asm"> ; 汇编示例 ; nasm boot.asm -o boot.bin ; partcopy boot.bin 0 200 -f0 [ORG 0x7c00] ; add to offsets start: xor ax, ax ; make it zero ... ; As before mov cr0, eax jmp 0x8:pmode pmode: mov bx, 0x10 ; select descriptor 2, instead of 1 mov ds, bx ; 10h = 10000b and al,0xFE ; back to realmode mov cr0, eax ; by toggling bit again jmp 0x0:huge_unreal huge_unreal: ... ;As before gdtinfo: dw gdt_end - gdt - 1 ;last byte in table dd gdt ;start of table gdt dd 0,0 ; entry 0 is always unused flatcode db 0xff, 0xff, 0, 0, 0, 10011010b, 10001111b, 0 flatdata db 0xff, 0xff, 0, 0, 0, 10010010b, 11001111b, 0 gdt_end: times 510-($-$$) db 0 ; fill sector w/ 0's dw 0xAA55 ; Required by some BIOSes </source> 警告:这可能在某些模拟器或某些硬件上不起作用。 == 编译器支持 == ===Smaller C=== [[Smaller C]]编译器支持非实模式。 它为虚实模式生成[[MZ]]可执行文件(可以用[[BootProg]]加载)。 代码和堆栈将位于1MB标记以下,并且堆栈大小受64KB限制 (瞧,CS:(E)IP,SS:(E)SP,这是DOS中MZ可执行文件的自然设置)没有什么不寻常的。 DS和ES段寄存器设置为0,因此C指针可以作为平面32位物理地址和地址数据或内存映射设备在前4 GB内存中的任何位置工作。 这些可执行文件的启动代码执行必要的重定位(只有自定义重定位,没有标准的MZ重定位,这可能会简化可执行文件的加载),并在将控制权传递给等价的“main()”之前设置非真实模式。 有关如何编写虚实模式的汇编代码位的信息,请参阅编译器源代码树中srclib下的“srclib/c0du.asm”和其他C/汇编代码(请查看#ifdef__unreal__‘下的(“内联汇编”)”)。 你可以在DOS中尝试非实模式 (例如在DOSBox,VirtualBox FreeDOS中),因为编译器完全支持其C库中的DOS非实模式组合。 ''tests/vesalfb.c''是一个简单的例子,可以在启用线性帧缓冲区的情况下设置[[VESA]]图形模式,并在屏幕上以非真实模式绘制一些东西。 有关用Smaller C实现非实模式[[BootLoader]]的示例,请参阅[https://github.com/fysnet/FYSOS/tree/master/loader FYSOS]。 [[Category:X86 CPU]] [[Category:FAQ]]
返回至“
Unreal Mode
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
变体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息