Big Real Mode 入坑

想必接触操作系统的朋友一定对real mode不陌生,那么,你知道big real mode吗?

Big Real Mode与Real Mode十分相似,这种模式可以说是介于Real Mode与Protect Mode之间,在这种模式下,你可以访问4GB的内存,但你的指令编码仍然是16位的。

以下是一个big real mode进入示例,仅供参考:

big_real:
        
        mov     ax, 0x2401
        int     0x15 ;open A20

        cli
        db      0x66
        lgdt    [cs:gdtr]

        mov     eax, cr0
        or      eax, 1
        mov     cr0, eax

        mov		ax, 0x10; data
        mov		fs, ax

        mov		eax, cr0
        and		 al, 0xfe
        mov		cr0, eax

        sti
        push    0x0000
        pop     fs
        ret
        gdt:        dq      0
            dq      0x004F9A000000FFFF ; code
            dq      0x00CF92000000FFFF ; data for fs 
        gdtr  :     dw      23
            dd      gdt

请注意,有些资料表示,在物理机中,重新为fs赋值将会导致fs段寄存器失去32位寻址功能,

但笔者在物理机中实验过后,却发现事实并非如此,重新赋值并不会导致段寄存器失去32位寻址功能,而是会让寻址紊乱。换句话说,在real mode中,寻址模式为段寄存器*0x10+偏移;在big real mode中,寻址模式则为段基地址+偏移(有点像protect mode),但是如果重新赋值的话,就会变成原来的段寄存器*0x10+偏移,不过偏移可以是32位的。

如果fs=0x10的话,会导致一些问题,比如有些BIOS中断例程过于负责,它可能是以下这样的:

bios_int:
    push fs
    push gs
    ...
    pop  gs
    pop  gs
    iret

这会导致后续代码寻址紊乱。换句话说,如果fs的值是0x10,那么返回后由于fs被重新赋值,寻址模式发生了改变,导致出现一些奇葩的问题,比如这一段代码:

;fs=0x10
push fs
pop  fs
mov eax, 0x00000000
mov [fs:eax], byte 0x41

这段代码执行后,0x0000_0000并不会出现0x41,0x41将出现在0x0000_0100.

如果fs=0x00,就不会出现这样的问题,因此,笔者在big_real函数中加入把fs赋值为0的代码。

而且在物理机中,只要打开了A20即可(不必大费周折去进入保护模式),因此,在物理机中big_real函数还可以继续简化,如下:

 big_real:
        mov     ax, 0x2401
        int     0x15 ;open A20

        push    0x0000
        pop     fs
        ret

以上说的都是物理机的情况,那么,虚拟机的情况如何呢?

首先,重新为fs赋值不会导致紊乱,寻址模式仍然为段寄存器基地址+偏移,但是,代码不能像刚刚那一段那么简化,还是得回到之前的第一段代码,所以可以说,以下之前的第一段代码是通用的

big_real:
        
        mov     ax, 0x2401
        int     0x15 ;open A20

        cli
        db      0x66
        lgdt    [cs:gdtr]

        mov     eax, cr0
        or      eax, 1
        mov     cr0, eax

        mov		ax, 0x10; data
        mov		fs, ax

        mov		eax, cr0
        and		 al, 0xfe
        mov		cr0, eax

        sti
        push    0x0000
        pop     fs
        ret
        gdt:        dq      0
            dq      0x004F9A000000FFFF ; code
            dq      0x00CF92000000FFFF ; data for fs 
        gdtr  :     dw      23
            dd      gdt

还有一点要特别注意:在物理机中的Big Real Mode,任何段寄存器都有32位寻址能力,然而在虚拟机中,只有在保护模式为之赋值的段寄存器才能拥有32位的寻址能力,其他没有在保护模式下赋值的段寄存器就只有16位寻址能力。

比如这段代码:

call big_real
push 0
pop gs
mov eax, 0x00000000
mov [gs: eax], byte 0x41

如果在虚拟机中运行,最后一行会导致宕机;如果在物理机中运行,最后一行可以正常运行。

对了,笔者用的两台物理机处理器都是Inter的64位处理器;第三台虚拟机是VMWare,在amd64上运行,版本是17.0.1。如果笔者有什么错误之处,欢迎大家在评论区加以指正。 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值