![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-09-15 05:03 |
共 47,812 主题排行 / 349,917 发帖 / 今日 0 篇 / 48,268 会员排行 |
| DOS开发编程 & 发展交流 (开发室) » 求教:在DOS实模式下怎么突破640K? |
| 可打印版本 1,944 / 6 |
| 第1楼 crscd | 发表于 2003-07-15 00:00 |
| 初级用户 发帖 4 积分 116 | |
|
求教:在DOS实模式下怎么突破640K? 我正在作一个在DOS实模式下的应用软件,但是可执行文件的SIZE 为700K,在DOS实模式下不能运行,请问各位大侠采取那些措施可以减小可执行文件的SIZE,或怎么突破实模式的限制,怎么使用640-1M间的扩充内存?谢谢!!!
|
|
| 第2楼 garychang | 发表于 2003-07-16 00:00 |
| 初级用户 发帖 9 积分 136 | |
|
切入保護模式就好了阿。
|
|
| 第3楼 Dark-Destroy | 发表于 2003-07-16 00:00 |
| 元老会员 发帖 3,551 积分 8,312 | |
|
還有一種方式,使用XMS
|
|
| 第4楼 Roy | 发表于 2003-07-16 00:00 |
| 管理员 发帖 1,633 积分 4,869 | |
|
還有DPMI,VCPI和EMS呢...
|
|
| 第5楼 Dark-Destroy | 发表于 2003-07-16 00:00 |
| 元老会员 发帖 3,551 积分 8,312 | |
|
EMS現在沒人用了吧.....
|
|
| 第6楼 crscd | 发表于 2003-07-21 00:00 |
| 初级用户 发帖 4 积分 116 | |
|
能说的详细一点吗?怎么使用XMS |
|
| 第7楼 凌晨一点 | 发表于 2003-10-25 00:00 |
| 初级用户 发帖 54 积分 255 | |
|
实方式下XMS中的图象数据直接访问方法
直接访问4GB内存 无论CPU在实方式下或保护方式下,其物理地址的形成都将使用段描述符寄存器。对于CPU在形成物理地址时,实方式与0特权级不分页的保护方式是相同的。只是对段的基地址和段的界限值设置不同。 当CPU复位后,CPU处于实方式下,段描述符寄存器的界限值被自动设置为64KB,段描述符寄存器的基地址可通过对段寄存器的赋值最大只能设置为FFFFH×16。因此,段内的寻址空间只能为64KB,CPU访问内存的空间只能为FFFFH×16+64KB。 基于CPU物理地址形成的统一性,,在实方式下直接访问4GB内存的关键是扩大段描述符寄存器的界限值。使诸如“MOV AX,”指令的32位寄存器间接寻址操作实现4GB内存的访问。然而,CPU在实方式下并没有提供改变段描述符寄存器的界限值的操作指令。改变段描述符寄存器的内容只能在保护方式下进行。当设置控制寄存器CR0的PE位=1时,CPU进入保护方式;当设置控制寄存器CR0的PE位=0时,CPU返回实方式。通过设置CR0改变工作方式时,段描述符寄存器的内容不发生变化。因此,在DOS实方式下直接访问4GB内存之前,让CPU进入保护方式下,通过装载具有4GB界限的段描述符到段描述符寄存器DS、ES、FS和GS中去。然后返回到实方式下。就可使诸如“MOV AX,”、“MOV AX,FS:”指令的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={0}; //存放GDT的基地址和长度 void set4gb( ) { asm{ cli //关中断 mov word ptr GDT_Addr, (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, 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:, ah //源图象数据与阈值进行比较 asm mov al, 0 //如果源图象数据<阈值,al=0 asm jc TN1 asm mov al, 255 //如果源图象数据≥阈值,al=255 TN1: asm mov fs:, al //存运算结果到二值化数据块中 asm inc esi //源图象数据块的32位线性地址增一 asm inc edi //二值化图象数据块的32位线性地址增一 asm loopd TN0 } ④程序结构 void main( ) { openA20( ); set4gb( ); … … //用户程序 } 距你发贴的时间已有两三个月了,也不晓得有没有用^_^ |
|
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |