中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » 求教:在DOS实模式下怎么突破640K?
作者:
标题: 求教:在DOS实模式下怎么突破640K? 上一主题 | 下一主题
crscd
初级用户




积分 116
发帖 4
注册 2003-7-15
状态 离线
『楼 主』:  求教:在DOS实模式下怎么突破640K?

我正在作一个在DOS实模式下的应用软件,但是可执行文件的SIZE 为700K,在DOS实模式下不能运行,请问各位大侠采取那些措施可以减小可执行文件的SIZE,或怎么突破实模式的限制,怎么使用640-1M间的扩充内存?谢谢!!![em24]

2003-7-15 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
garychang
初级用户




积分 136
发帖 9
注册 2003-6-30
状态 离线
『第 2 楼』:  

切入保護模式就好了阿。

2003-7-16 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
Dark-Destroy
元老会员





积分 8312
发帖 3551
注册 2003-3-22
状态 离线
『第 3 楼』:  

還有一種方式,使用XMS



MSN:tiqit2@hotmail.com
2003-7-16 00:00
查看资料  发送邮件  访问主页  发短消息 网志   编辑帖子  回复  引用回复
Roy
管理员

專業島民



积分 4869
发帖 1633
注册 2002-12-10
状态 离线
『第 4 楼』:  

還有DPMI,VCPI和EMS呢...



我的網站:http://mw16.2ya.com/ 我的網誌: http://scrappedblog.blogspot.com/
~
我的Winamp正在播放的歌曲:
2003-7-16 00:00
查看资料  发短消息 网志   编辑帖子  回复  引用回复
Dark-Destroy
元老会员





积分 8312
发帖 3551
注册 2003-3-22
状态 离线
『第 5 楼』:  

EMS現在沒人用了吧.....



MSN:tiqit2@hotmail.com
2003-7-16 00:00
查看资料  发送邮件  访问主页  发短消息 网志   编辑帖子  回复  引用回复
crscd
初级用户




积分 116
发帖 4
注册 2003-7-15
状态 离线
『第 6 楼』:  能说的详细一点吗?怎么使用XMS

[em05]

2003-7-21 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
凌晨一点
初级用户




积分 255
发帖 54
注册 2003-10-24
状态 离线
『第 7 楼』:  

实方式下XMS中的图象数据直接访问方法
  直接访问4GB内存
  无论CPU在实方式下或保护方式下,其物理地址的形成都将使用段描述符寄存器。对于CPU在形成物理地址时,实方式与0特权级不分页的保护方式是相同的。只是对段的基地址和段的界限值设置不同。
  当CPU复位后,CPU处于实方式下,段描述符寄存器的界限值被自动设置为64KB,段描述符寄存器的基地址可通过对段寄存器的赋值最大只能设置为FFFFH×16。因此,段内的寻址空间只能为64KB,CPU访问内存的空间只能为FFFFH×16+64KB。
  基于CPU物理地址形成的统一性[1],[2],在实方式下直接访问4GB内存的关键是扩大段描述符寄存器的界限值。使诸如“MOV AX,[EBX]”指令的32位寄存器间接寻址操作实现4GB内存的访问。然而,CPU在实方式下并没有提供改变段描述符寄存器的界限值的操作指令。改变段描述符寄存器的内容只能在保护方式下进行。当设置控制寄存器CR0的PE位=1时,CPU进入保护方式;当设置控制寄存器CR0的PE位=0时,CPU返回实方式。通过设置CR0改变工作方式时,段描述符寄存器的内容不发生变化。因此,在DOS实方式下直接访问4GB内存之前,让CPU进入保护方式下,通过装载具有4GB界限的段描述符到段描述符寄存器DS、ES、FS和GS中去。然后返回到实方式下。就可使诸如“MOV AX,[EBX]”、“MOV AX,FS:[EBX]”指令的32位寄存器间接寻址操作实现4GB内存的访问。
  由于这种编程方法产生的是基于实方式下的执行程序。因此,它不能在保护方式下和虚拟8086方式下运行,即,不能在Windows中运行,也不能在DOS系统中装载扩充内存EMS驱动程序(如EMM386.EXE)。

编程方法
(1)编程环境
  本文采用Borland C++ 3.1程序设计环境,在程序中使用内嵌汇编方法实现特定的操作,在Options的“Compile”-“Advanced Code generation”中选择386指令集。由于集成开发环境下的内部编译器不能识别内嵌的386汇编指令,要实现32位寄存器和32位地址操作汇编指令,可让集成开发环境调用TASM.EXE进行编译,即设置Options中的“Compile”-“Code generation”-“Compile via assemler”为ON。这样便可完整地运用386汇编指令,在以下编程示例中采用了这种编译方法。
(2)基本操作函数
  ①打开A20地址线
  要访问4GB内存,必须打开A20地址线。
void openA20()
{ while(inp(0x64) & 2); outp(0x64,0xd1);
while(inp(0x64) & 2); outp(0x60,0xdf);
while(inp(0x64) & 2); outp(0x64,0xff);
}
②设置数据段的4GB界限函数
  首先,建立一个全局描述符表GDT,即GDT_def,它含有二个描述符,第一个为空描述符(保护方式下系统要求的),第二个是具有4GB段界限的数据段描述符。它的选择字为8。再计算出GDT的基地址和长度存入GDT_Addr中。然后,装载GDT,进入保护方式,把选择字8赋给FS和GS,此时第二个数据段描述符被装载到FS和GS的描述符寄存器中。最后返回实方式。通理,也可设置DS和ES的4GB界限。
unsigned long GDT_def[ ]={0,0,0x0000FFFF,0x008F9200}; //全局描述符表GDT

unsigned char GDT_Addr[6]={0}; //存放GDT的基地址和长度
void set4gb( )
{ asm{
cli //关中断
mov word ptr GDT_Addr[0], (2*8-1) //GDT的长度存入GDT_Addr中
mov eax, ds //计算GDT描述符表的线性基地址31~0
shl eax, 4 //段地址eax=ds×16
xor ebx, ebx //ebx清零
mov bx, offset GDT_def //bx=GDT的偏移地址
add eax,ebx //GDT的线性基地址=eax+ebx
mov dword ptr GDT_Addr[2], eax //GDT的线性基地址存入GDT_Addr中
lgdt fword ptr GDT_Addr //将GDT_Addr装载到GDTR寄存器中
mov bx, 8 //设置数据段描述符的选择字
mov eax, cr0
or al,1
mov cr0,eax //设置CR0的PE位=1
jmp flush1 //进入保护方式
}
flush1: asm{
mov fs,bx //FS装载具有4GB界限的数据段描述符
mov gs,bx //GS装载具有4GB界限的数据段描述符
and al,0feh
mov cr0,eax //设置CR0的PE位=0
jmp flush2 //返回实方式
}
flush2: asm{
mov ax, 0
mov fs,ax //设置FS描述符的基地址为0
mov gs,ax //设置GS描述符的基地址为0
sti //开中断
}
}
③直接访问4GB内存的编程示例
 在FS和GS具有4GB的访问界限后,通过32位寄存器间接寻址的指令就可实现4GB内存的访问。例如图象二值化的运算函数如下:
void two_mem(unsigned long addrd, unsigned long addrs, unsigned long leng,
unsigned char yuzi)
{ asm mov ecx, leng //leng为图象数据块的字节数
asm mov esi, addrs //addrs为源图象数据块的32位线性基地址
asm mov edi, addrd //addrd为二值化图象数据块的32位线性基地址
asm mov ah, yuzi //yuzi为阈值
TN0: asm cmp fs:[esi], ah //源图象数据与阈值进行比较
asm mov al, 0 //如果源图象数据<阈值,al=0
asm jc TN1
asm mov al, 255 //如果源图象数据≥阈值,al=255
TN1: asm mov fs:[edi], al //存运算结果到二值化数据块中
asm inc esi //源图象数据块的32位线性地址增一
asm inc edi //二值化图象数据块的32位线性地址增一
asm loopd TN0
}
④程序结构
void main( )
{ openA20( );
set4gb( );
… … //用户程序
}

  距你发贴的时间已有两三个月了,也不晓得有没有用^_^

2003-10-25 00:00
查看资料  发送邮件  发短消息 网志  OICQ (285749694)  编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: