bini 发表于 2008-10-8 14:29:37

DOS 4G big real Mode Demo code。

刚学习的同学,有些还不会,我这里贴点C和asm的代码。只供参考。

这是C的/********************************************************************
*    File: DOS4G.H                                                *
*       Compile with BC 3.1 ( Editor: Tab size = 4 )                *
*                                                                   *
*    ========================Title===============================   *
*      这个函数是让系统进入DOS 4G模式                           *
*       程序参考了:陈家琪《DOS实方式下直接访问4GB》                *
*                                                                   *
*       使用: openA20(); set4gb();                                  *
*                                                                   *
*   ===========================History==========================    *
*    author: bini                                                   *
*      date: 2004-11-30Frist version.                           *
********************************************************************/

#include <conio.h>
#pragma inline

/***********************************************
*    两个GDT,第一个为系统使用,不管,默认为0   *
*    第二个为一个数据段,没有代码段。         *
***********************************************/
unsigned long GDT_def[ ]={0,0,      /*系统使用*/
                        0x0000FFFF, /* hi16bit( 0~15 ) is base low=0,
                                       low16bit( 0~15 ) is limit low=0xFFFF
                                    */
                        0x008F9200};/* 最低字节为 base( bit 16~23 )
                                       最高字节为 base( bit 24~31 )
                                       
                                       属性Attrib = 0x8F92
                                       
                                             属性位Hibyte低四位为
                                                 Limit( 16~19 )=F
                                             属性位Hibyte bit7 为粒度
                                                 (值1=4KB粒度)
                                                 8F & 0x80 = 1
                                                
                                             属性位Lowbyte低四位为段类型,值=2
                                                 表示为可读/写段
                                             属性位Hibyte高四位=9,bit3=1表示:
                                                 描述符对地址转换是有效的。
                                                 bit0=1表示为:
                                                 系统段描述符。而不是门描述符。
                                             
                                       */

/****************************************
*    GDTR寄存器, 48bit=6bytes            *
*    +-------------------------------+   *
*    |   32bit基地址       |16bit界限|   *
*    +-------------------------------+   *
****************************************/
unsigned char GDT_Addr={0};

/****************
*    打开A20门    *
****************/
void openA20(void)
{
    asm{
      pusha
      in         al, 92H
      or         al, 0x02
      out      0x92, al
      out      0xed, al
      popa
    }
}

/***********************************************
*    函数功能:进入DOS4G                     *
*    ====================                      *
*                                              *
*    GDT描述符界限计算方式:描述符个数*8-1   *
*   如:                                       *
*      mov    word ptr GDT_Addr, (2*8-1); *
*       表示为 2个GTD                        *
*                                              *
*    选择子为所在描述符内的字节偏移。          *
*                                              *
***********************************************/
void set4gb(void)
{
    asm{
      cli
      /****************************************
      *    GDTR寄存器                        *
      *    +-------------------------------+   *
      *    |   32bit基地址       |16bit界限|   *
      *    +-------------------------------+   *
      *****************************************/
      /*********************
      *      得出段界限       *
      *********************/
      mov      word ptr GDT_Addr, (2*8-1);
      /********************************************
      *    计算GDT表的32位基地址,存入GDTR      *
      ********************************************/
      mov      eax, ds
      shl      eax, 4
      xor      ebx, ebx
      mov      bx, offset GDT_def
      add      eax, ebx
      mov      dword ptr GDT_Addr, eax
      lgdt       fword ptr GDT_Addr
      /********************
      *   选择子偏移      *
      ********************/
      mov      bx, 8
      mov      eax, cr0
      or         al, 1
      /**********************
      *   进入保护模式    *
      **********************/
      mov      cr0, eax
      jmp      pMod
    }

    pMod: asm{
         /************************************************************
         * 让fs与gs加载选择子,使其能访问 0xFFFFF * 4K (4GB) 空间    *
         ************************************************************/
      mov      fs, bx
      mov      gs, bx
      and      al, 0x0FE
      /******************
      * 进入实模式      *
      ******************/
      mov      cr0, eax
      jmp      rMod
       }

    rMod: asm{
      /* ******************************************************************
      * 退出,fs、gs清0,访问系统内存可用: gs   *
      ********************************************************************/
      mov      ax, 0
      mov      fs, ax
      mov      gs, ax
      sti
    }
}这是asm的;/********************************************************************
;*    File: DOS4G.asm                                                *
;*       Compile with masm ( Editor: Tab size = 4 )                  *
;*                                                                   *
;*    ========================Title===============================   *
;*      这个demo是让系统进入DOS 4G模式,进行数据访问               *
;*                                                                   *
;*   ===========================History==========================    *
;*    author: bini                                                   *
;*      date: 2008-10-08Frist version.                           *
;********************************************************************/
.model small
.586p

DSEGSEGMENT   USE16               ;16位数据段

DESC            STRUC
      LimitL          DW      0 ;段界限(BIT0-15)
      BaseL         DW      0 ;段基地址(BIT0-15)
      BaseM         DB      0 ;段基地址(BIT16-23)
      Attributes      DB      0 ;段属性
      LimitH          DB      0 ;段界限(BIT16-19)(含段属性的高4位)
      BaseH         DB      0 ;段基地址(BIT24-31)
DESC            ENDS

PDesc         STRUC
      Limit         DW      0 ;16位界限
      Base            DD      0 ;32位基地址
PDesc         ENDS

GDT_def         Label   Fword
Null_Desc       DESC    <   0h,0h, 00h, 00h, 000h, 0>
Data_Desc       DESC    < 0FFFFh,0h, 00h, 92h, 08Fh, 0>

GDT_Addr      PDesc   <$-GDT_def-1, >
DSEG            ENDS                        ;数据段定义结束

CSEG            SEGMENT USE16               ;16位代码段
                ASSUMECS:CSEG,DS:DSEG
.Startup
      call      Set4gb
;
;       fs, gs即能访问4GB空间
;       write your code in here.
;
      .exit
      
Set4gb          PROC      NEAR
      in      al, 92h
      or      al, 002
      out       092h, al
      out       0edh, al

      cli

;      mov      word ptr GDT_Addr, (2*8-1);

      mov       eax, ds
      shl       eax, 4
      xor       ebx, ebx
      mov       bx, offset GDT_def
      add       eax, ebx
      mov       dword ptr GDT_Addr.Base, eax
      lgdt      fword ptr GDT_Addr

      mov       bx, 8
      mov       eax, cr0
      or      al, 1
      mov       cr0, eax

      jmp       pMod
    pMod:

      mov       fs, bx
      mov       gs, bx
      and       al, 0FEh
      mov       cr0, eax
      
      jmp       rMod
    rMod:

      mov       ax, 0
      mov       fs, ax
      mov       gs, ax
      
      ; 在2M的位置测试写一下数据
      mov       esi, 200000h
      mov       dword ptr fs:, 055aa55aah
      ; 用RU去看看200000h的位置是否是此数据....

      sti
      ret
Set4gbENDP
      
CSEG         ENDS                              ;代码段定义结束
      end

laoshumice 发表于 2008-10-14 14:48:07

学习,学习了,楼主辛苦了

beervista 发表于 2008-12-15 17:20:53

有一个问题,我用BC31为什么没法编译32位的汇编指令呢?要设置哪儿吗?

happybasic 发表于 2008-12-18 17:11:16

option->compiler->advanced code generation中的instruction set选 80386

option->compiler->code generation中的option选中, compile via assembler

[ 本帖最后由 happybasic 于 2008-12-20 15:41 编辑 ]

aioliy 发表于 2009-6-4 20:55:40

太强了 学习 只是更新的比较慢哈 谢谢了

Faintsnow 发表于 2009-6-5 11:04:27

Undefined symbol: &LT

charles 发表于 2009-6-8 17:07:20

Null_Desc       DESC    &lt;   0h,0h, 00h, 00h, 000h, 0&gt;
Data_Desc       DESC    &lt; 0FFFFh,0h, 00h, 92h, 08Fh, 0&gt;

GDT_Addr      PDesc   &lt;$-GDT_def-1, &gt;
替换如下,
Null_Desc       DESC    < 0h,0h, 00h, 00h, 000h, 0>
Data_Desc       DESC   <0FFFFh,0h, 00h, 92h, 08Fh, 0>

GDT_Addr      PDesc   <$-GDT_def-1, >
这样你就能编译通过并且可以运行

Faintsnow 发表于 2009-6-9 11:23:21

替换了就OK.Thanks

bini 发表于 2009-8-1 00:44:39

这个是Discuz的Bug.有空翻出来改改看。发代码<>符号被Discuz 在[ code ]里变成HTML的东西.

A_jack 发表于 2010-2-26 10:47:24

原帖由 happybasic 于 2008-12-18 17:11 发表 http://www.ufoit.com/bbs/images/common/back.gif
option->compiler->advanced code generation中的instruction set选 80386

option->compiler->code generation中的option选中, compile via assembler
   作了上述设置之后还是不行,编译的时候提示: cannot find executable: TASM. 我换了几个版本的TASM还是没用,除非拿掉含有32位寄存器的那些code才行。这个是什么原因,请各位大侠多多指教

beervista 发表于 2010-4-12 10:27:08

原帖由 A_jack 于 2010-2-26 10:47 发表 http://www.ufoit.com/bbs/images/common/back.gif

   作了上述设置之后还是不行,编译的时候提示: cannot find executable: TASM. 我换了几个版本的TASM还是没用,除非拿掉含有32位寄存器的那些code才行。这个是什么原因,请各位大侠多多指教 ...

我也是相同的问题,请问哪位有解,谢了!

jdf 发表于 2011-2-21 21:04:39

option->compiler->Transfer 设置TASM的路径,就不会提示找不到TASM;
还要把TASMMSG.exe拷贝到源代码(工程目录),就可以编译完成了。
页: [1]
查看完整版本: DOS 4G big real Mode Demo code。