程序原理:

CPU上电后,从ROM 中的BIOS开始运行。
BIOS是处在内存的最顶端64KB(FFFF0000H),还是1MB之下的64KB(F0000H)处呢?事实上,BIOS在这两个地方都同时出现。
在保护模式时,CS是08H的选择子,到了实模式时,CS还是08H,但地址不会突然变成80H加上偏移量。
也就是说,实模式与0特权级保护模式不分页时是一模一样的。
所以,实模式下一样可以处理通常被认为只有在保护模式才能做的事,比如访问整个机器的内存。
实际上,Intel本身就在使用这种办法,使得CPU上电时能从FFFFFFF0H处开始第一条指令。

程序功能:

  1. 不需要在保护模式状态下就可以直接把386的4GB内存读出来;
  2. 利用此程序可直接在DOS中做物理设备的检测。
  3. 在DOS下,可根据此类方法将中断向量表移到任意位置,达到反跟踪或其他等目的。

程序执行过程:

  程序运行后,等用户从键盘输入一个字符。

  当输入“Q”字符时,整个程序将退出;

  当输入“D”时,将在屏幕上显示一屏内存的数据:

    最左边为绝对地址,其后一列显示的是以十六进制位表示的内存的数据,后一列是数据所对应的ASCII码。

代码关键分析:

(1)IP=0000FFF0H

CS∶EIP等于FFFFFFF0H。

(2)段寄存器FS在实模式下无法装入4GB的地址和权限。

所以让CPU进入一会儿保护模式,在装入了FS之后马上回到实模式。

保护模式进入方式:建好GDT,把CR0寄存器的位0置上1。

把一个包含有4GB地址空间的值装入FS之后,就可返回实模式。

(3)预先可建好GDT如下:

unsigned long GDT-Table[]=

{

  0,0,                        //空描述符,必须为零

  0x0000FFFF,0xCF9A00,        //32位平面式代码段

  0x0000FFFF,0xCF9200         //32位平面式数据段

}

(4)进入保护模式时要关闭所有的中断:把IDTR的界限设置为0,CPU自动关闭所有中断,包括NMI。

返回实模式后恢复IDTR并开中断。

(5)A20地址线的控制对于正确访问整个内存也很重要。

在进入保护模式前,要让8042打开A20地址线,否则会出现4GB内存中的混乱。

(6)此程序用BC 3.1编译连接,其连接器不能为DOS程序处理32位寄存器,所以直接在代码中加入操作码前缀0x66和地址前缀0x67,以便让DOS实模式下的16位程序可用32位寄存器和地址。程序的右边以注释形式给出等效的32位指令。

注意:16位的指令中,mov al, byte ptr [BX]的指令码正好是32位的指令mov al, byte ptr[EDI]。

附代码:

#include <dos.h>

unsigned long   GDT_Table[]=

{    0,  0,                         //NULL   - 00H    0x0000FFFF, 0x00CF9A00,     //Code32 - 08H Base=0 //Limit=4G-1 Size=4G    0x0000FFFF, 0x00CF9200      //Data32 - 10H Base=0 //Limit=4G-1 Size=4G};

//Save The IDTR before Enter Protect Mode.unsigned char   OldIDT[6]={0};

//NULL The IDTR,IDTR's Limit=0 will disable all //Interrupts,include NMI.unsigned char   pdescr_tmp[6]={0};  

#define KeyWait()   {while(inportb(0x64)&2);}

void        A20Enable(void){        KeyWait();        outportb(0x64,0xD1);        KeyWait();        outportb(0x60,0xDF);    //Enable A20 with 8042.        KeyWait();        outportb(0x64,0xFF);        KeyWait();

}void        LoadFSLimit4G(void){A20Enable();                //Enable A20

//**************************************//*       Disable ints & Null IDT      *//**************************************    asm {            CLI                //Disable inerrupts            SIDT    OldIDT      //Save OLD IDTR            LIDT    pdescr_tmp  //Set up empty IDT.Disable any interrupts,Include NMI        }

//***************************************//*     Load GDTR       *//***************************************    asm { //The right Code is Real,But BC++'s Linker NOT Work //with 32-bits Code.        db  0x66        //32 bit Operation Prefix in 16 Bit DOS.        MOV CX,DS       //MOV   ECX,DS        db  0x66        //Get Data segment physical Address        SHL CX,4        //SHL   ECX,4        MOV word ptr pdescr_tmp[0],(3*8-1)          //MOV   word ptr pdescr_tmp[0],(3*8-1)        db  0x66        XOR AX,AX   //XOR   EAX,EAX        MOV AX,offset GDT_Table//MOV   AX,offset GDT_Table        db  0x66        ADD AX,CX   //ADD   EAX,ECX        MOV word ptr pdescr_tmp[2],AX                    //GDTR Base high16 bits        db  0x66        SHR AX,16   //SHR   EAX,16        MOV word ptr pdescr_tmp[4],AX                       //GDTR Base high16 bits        LGDT    pdescr_tmp  //Load GDTR}

    //**************************************//*  Enter 32 bit Flat Protected Mode  *//**************************************//  Set CR0 Bit-0 to 1 Enter 32 Bit Protection//Mode,And NOT Clear machine perform cache,It Meaning//the after Code HAD Ready To RUN in 32 Bit Flat Mode,//Then Load Flat Selector to FS and Description into it's//Shadow register,After that,ShutDown Protection Mode//And ReEnter Real Mode immediately.//  The FS holds Base=0 Size=4G Description and//it can Work in Real Mode as same as Pretect Mode,//untill FS be reloaded.//  In that time All the other Segment Registers are//Not Changed,except FS.(They are ERROR Value holded in CPU).

    asm {        MOV DX,0x10                 //The Data32 Selector        db  0x66,0x0F,0x20,0xC0     //MOV   EAX,CR0        db  0x66        MOV BX,AX                   //MOV   EBX,EAX        OR  AX,1        db  0x66,0x0F,0x22,0xC0     //MOV   CR0,EAX//Set Protection enable bit    JMP Flush

        }               //Clear machine perform cache.    Flush:              //Now In Flat Mode,But The //CS is Real Mode Value.    asm {                    //And it's attrib is 16-Bit Code //Segment.        db  0x66        MOV AX,BX           //MOV   EAX,EBX        db  0x8E,0xE2           //MOV   FS,DX   //Load FS now        db  0x66,0x0F,0x22,0xC0                             //MOV   CR0,EAX//Return Real Mode.Now FS's Base=0 Size=4G        LIDT        OldIDT                  //LIDT  OldIDT Restore IDTR        STI                 //STI       Enable INTR        }}

//With FS can Access All 4G Memory Now.But if FS be reloaded //in Real Mode It's Limit will Be Set to FFFFh(Size=64K),//then Can not used it// to Access 4G bytes Memory Again,Because FS is Segment:Offset//Memory type after that.//If Use it to Access large than 64K will generate Execption 0D.//unsigned char ReadByte(unsigned long Address){    asm db  0x66    asm mov di,word ptr Address //MOV   EDI,Address    asm db  0x67                    //32 bit Address Prefix    asm db  0x64                    //FS:    asm mov al,byte ptr [BX]        //=MOV AL,FS:[EDI]    return  _AL;}

unsigned char   WriteByte(unsigned long Address){    asm db  0x66    asm mov di,word ptr Address //MOV   EDI,Address    asm db  0x67                    //32 bit Address Prefix    asm db  0x64                    //FS:    asm mov byte ptr [BX],al        //=MOV FS:[EDI],AL    return  _AL;}

///// Don't Touch Above Code /#include <stdio.h>///打印出Address指向的内存中的数据///void    Dump4G(unsigned long Address){        int i;        int j;        for(i=0;i<20;i++)        {            printf("%08lX: ",(Address+i*16));            for(j=0;j<16;j++)                printf("%02X ",ReadByte(Address+i*16+j));            printf("");            for(j=0;j<16;j++)            {                if(ReadByte(Address+i*16+j)<0x20) printf(".");                else printf("%c",ReadByte(Address+i*16+j));            }            printf("\n");        }

}

int main( void ){        char        KeyBuffer[256];        unsigned long   Address=0;        unsigned long   tmp;         LoadFSLimit4G();        printf("====Designed By Southern.1995.7.17====\n");        printf("Now you can Access The Machine All 4G Memory.\n");        printf("Input the Start Memory Physical to DUMP.\n");        printf("Press D to Cuntinue DUMP,0 to End & Quit.\n");        do  {            printf("-");            gets(KeyBuffer);            sscanf(KeyBuffer,"%lX",&tmp);            if(KeyBuffer[0]=='q') break;            if(KeyBuffer[0]=='d') Address+=(20*16);            else Address=tmp;            Dump4G(Address);            }while(Address!=0);        return 0;}

转载于:https://www.cnblogs.com/gengzhikui/archive/2011/12/15/2288605.html

DOS下读取4GB内存——梁肇新代码分析相关推荐

  1. DOS下读取4GB内存

    好文章我收集下起来 CPU上电后,从ROM 中的BIOS开始运行. BIOS是处在内存的最顶端64KB(FFFF0000H),还是1MB之下的64KB(F0000H)处呢?事实上,BIOS在这两个地方 ...

  2. “软件狂”:梁肇新的成长之路(转载)

    "软件狂":梁肇新的成长之路 北京世纪豪杰计算机技术有限公司总裁梁肇新 1993年广西大学机械制造专业毕业 1994年进入珠海巨人公司做软件开发 1997年个人研发出<超级解 ...

  3. 梁肇新 编程高手箴言 书评

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 引用地址 ...

  4. 《编程高手箴言》——梁肇新

    在自己漫长的摸索,碰碰撞撞地爬行,某一天读到这本书,相当认同.希望对后来者有帮助,不用再像我这样摸索爬行,效率低下. 一个程序员成长的六个阶段: 1.能熟练地使用某种语言,这相当于练武中的套路和架式这 ...

  5. autojs读取文字_Auto.js小白详细代码分析教程-如何阅读本文档 - Documentation

    本文档为Auto.js的文档,解释了Auto.js各个模块的API的使用方法.作用和例子. 文档借助Node.js的文档构建工具生成,并在github上开源(https://github.com/hy ...

  6. DOS 实方式下直接访问4GB 内存

    十堰市湖北汽车工业学院电气工程系(442002) 陈家祺 摘 要: 分析了80486CPU 的寻址机制, 提出了在实方式下直接访问4GB 内存的策略和C 程序设计方法. 关键词: DO S 程序 扩展 ...

  7. DOS下如何访问4G内存

    转载 首先解释几个基本概念: 1.保护模式和实模式 自从1969年推出第一个微处理器以来,Intel处理器就在不断地更新换代,从8086.8088.80286,到80386.80486.奔腾.奔腾Ⅱ. ...

  8. win7下4GB内存提示:找到4GB,可用2GB的解决方法--让你的win7支持4G内存

    今天我给自己的本本扩展了一下内存,但是发现在系统信息中提示"找到4GB,可用2GB"的怪异信息,百度了很久终于悟出了其中的奥妙,在新浪的一篇技术文章中,找到了解决方法,下面是该文章 ...

  9. 安装一个新的int 9中断例程【在DOS下,按Tab建后改变当前屏幕的显示颜色,其它键照常处理】...

    ;任务: ; 安装一个新的int 9中断例程 ;功能: ; 在DOS下,按Tab建后改变当前屏幕的显示颜色,其它键照常处理 1 assume cs:code 2 3 stack segment 4 d ...

最新文章

  1. 第一篇博客,纪念一下,终于开通啦!
  2. bookmark: partitioned tables in sql server 2005
  3. Django的下载及命令
  4. 消息队列的实践php,php消息队列处理实践 ,利用AMQP和redis两种方法
  5. java人体识别_用华为HMS ML kit人体骨骼识别技术,Android快速实现人体姿势动作抓拍...
  6. java jersey client,如何在Jersey-Client Java中实现重试机制
  7. 2019年10月数据库流行度排行:国产数据库鲲鹏正举 PostgreSQL同比增幅第一
  8. java中elapseTime设置新时间,Java ApplicationLike.getApplicationStartElapsedTime方法代码示例...
  9. 深度优先搜索-和为某数的所有组合
  10. 数据血缘关系图 工具_如何在论文中画出漂亮的插图?用它!丨城市数据派
  11. java scanner构造函数_Point类的构造函数(JAVA)
  12. Golang语言 零基础入门教程
  13. git下载、安装、配置与简单应用(git上路之始)
  14. CAD2017下载AutoCAD2017下载安装详细教程
  15. Linux Shell学习-第二讲(进阶篇)
  16. 教你如何批量修改图片分辨率?
  17. Cobaltstrike Socks 代理隧道
  18. 【考研英语语法】限定词详细总结
  19. SpringMVC实现全局异常处理器
  20. JS检查日期是否为工作日

热门文章

  1. 哪个开源工作流引擎更好?Flowable or Camunda ?
  2. 基于RFID资产管理系统下的车辆位置管理,实时定位,RFID固定资产管理
  3. h700整列卡直通配置_DELL服务器RAID H700,PERC H800阵列卡配置中文完全手册图解
  4. py-02-爬虫比价器
  5. 《PR基础教程入门篇-学习笔记》-001
  6. 红旗linux 桌面版 6.0 精简版 刻成光盘怎么安装不了,3分钟学会:安装红旗Linux桌面版6.0 SP1...
  7. 动物模型之肾衰竭模型 大鼠实验性ARF的最常用大鼠模型
  8. LOL服务器修改韩服,LOL客户端里面页面怎么改成韩服那样
  9. 问题解决:Excel将列数据按照奇偶行分列
  10. vue el-table 滚动条样式设置(谷歌、火狐)