China DOS Union

-- Unite DOS · Advance DOS · Grow DOS --

Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum
DOS stands for freedom, openness and progress. Let us work hard, learn from the openness and GNU spirit of FreeDOS and Linux, and together build and grow a free GNU GPL world!

中国DOS联盟论坛
The time now is 2026-08-01 03:28
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » [Help] How can I break through 640K in DOS real mode? View 1,852 Replies 6
Original Poster Posted 2003-07-15 00:00 ·  中国 北京 中电飞华
初级用户
Credits 116
Posts 4
Joined 2003-07-15 00:00
23-year member
UID 6961
Gender Male
Status Offline
I’m developing an application that runs under DOS real mode, but the executable SIZE is 700K, so it can’t run in DOS real mode. What measures can I take to reduce the executable SIZE, or how can I break through the real-mode limits, and how can I use the extended memory between 640K and 1M? Thanks!!!
Floor 2 Posted 2003-07-16 00:00 ·  中国 台湾 远传电信
初级用户
Credits 136
Posts 9
Joined 2003-06-30 00:00
23-year member
UID 6154
Gender Male
Status Offline
Just switch into protected mode.
Floor 3 Posted 2003-07-16 00:00 ·  中国 台湾 远传电信
元老会员
★★★★★
Credits 8,312
Posts 3,551
Joined 2003-03-22 00:00
23-year member
UID 1225
Gender Male
Status Offline
There’s another way too, use XMS
MSN:tiqit2@hotmail.com
Floor 4 Posted 2003-07-16 00:00 ·  中国 香港
管理员
★★★★
專業島民
Credits 4,869
Posts 1,633
Joined 2002-12-10 00:00
23-year member
UID 465
Gender Male
Status Offline
There are also DPMI, VCPI, and EMS...
我的網站:http://mw16.2ya.com/ 我的網誌: http://scrappedblog.blogspot.com/
~
我的Winamp正在播放的歌曲:
Floor 5 Posted 2003-07-16 00:00 ·  中国 台湾 远传电信
元老会员
★★★★★
Credits 8,312
Posts 3,551
Joined 2003-03-22 00:00
23-year member
UID 1225
Gender Male
Status Offline
No one uses EMS anymore now, right.....
MSN:tiqit2@hotmail.com
Floor 6 Posted 2003-07-21 00:00 ·  中国 北京 中电飞华
初级用户
Credits 116
Posts 4
Joined 2003-07-15 00:00
23-year member
UID 6961
Gender Male
Status Offline
Floor 7 Posted 2003-10-25 00:00 ·  中国 湖南 长沙 电信
初级用户
★★
Credits 255
Posts 54
Joined 2003-10-24 00:00
22-year member
UID 11864
Gender Male
Status Offline
Method for directly accessing image data in XMS under real mode
Directly access 4GB of memory
Whether the CPU is in real mode or protected mode, the formation of its physical address uses the segment descriptor registers. For the CPU when forming physical addresses, real mode and ring-0 non-paged protected mode are the same. The only difference is in how the segment base address and segment limit are set.
After the CPU is reset, the CPU is in real mode, and the limit value of the segment descriptor registers is automatically set to 64KB. The base address of the segment descriptor registers can be set through assignments to the segment registers, but at most it can only be set to FFFFH×16. Therefore, the address space within a segment can only be 64KB, and the memory space the CPU can access can only be FFFFH×16+64KB.
Based on the uniformity of CPU physical address formation ,, the key to directly accessing 4GB of memory in real mode is to enlarge the limit value of the segment descriptor registers. This allows 32-bit register indirect addressing operations in instructions such as “MOV AX,” to access 4GB of memory. However, in real mode the CPU does not provide any instruction to change the limit value of the segment descriptor registers. The contents of the segment descriptor registers can only be changed in protected mode. When the PE bit of control register CR0 is set to 1, the CPU enters protected mode; when the PE bit of control register CR0 is set to 0, the CPU returns to real mode. When the working mode is changed by setting CR0, the contents of the segment descriptor registers do not change. Therefore, before directly accessing 4GB of memory in DOS real mode, let the CPU enter protected mode, and load segment descriptors with a 4GB limit into the segment descriptor registers DS, ES, FS, and GS. Then return to real mode. This will allow 32-bit register indirect addressing operations in instructions such as “MOV AX,” and “MOV AX,FS:” to access 4GB of memory.
Since what this programming method produces is an executable based on real mode, it cannot run in protected mode or virtual 8086 mode; that is, it cannot run under Windows, nor can an EMS memory driver (such as EMM386.EXE) be loaded in the DOS system.

Programming method
(1)Programming environment
This article uses the Borland C++ 3.1 programming environment, and specific operations in the program are implemented with inline assembly. In Options “Compile”-“Advanced Code generation”, select the 386 instruction set. Since the internal compiler in the integrated development environment cannot recognize inline 386 assembly instructions, to use assembly instructions with 32-bit registers and 32-bit address operations, you can have the integrated development environment call TASM.EXE for compilation, that is, set Options “Compile”-“Code generation”-“Compile via assemler” to ON. This way, the 386 assembly instructions can be used completely, and this compilation method is used in the programming examples below.
(2)Basic operation functions
①Open the A20 address line
To access 4GB of memory, the A20 address line must be opened.
void openA20()
{ while(inp(0x64) & 2); outp(0x64,0xd1);
while(inp(0x64) & 2); outp(0x60,0xdf);
while(inp(0x64) & 2); outp(0x64,0xff);
}
②Function for setting a 4GB limit for the data segment
First, establish a global descriptor table GDT, namely GDT_def, which contains two descriptors. The first is a null descriptor (required by the system in protected mode), and the second is a data segment descriptor with a 4GB segment limit. Its selector is 8. Then calculate the base address and length of the GDT and store them in GDT_Addr. Next, load the GDT, enter protected mode, and assign selector 8 to FS and GS. At this time, the second data segment descriptor is loaded into the descriptor registers of FS and GS. Finally return to real mode. By the same reasoning, the 4GB limits of DS and ES can also be set.
unsigned long GDT_def={0,0,0x0000FFFF,0x008F9200}; //global descriptor table GDT

unsigned char GDT_Addr={0}; //stores the base address and length of the GDT
void set4gb( )
{ asm{
cli //disable interrupts
mov word ptr GDT_Addr, (2*8-1) //store the length of the GDT into GDT_Addr
mov eax, ds //calculate bits 31-0 of the linear base address of the GDT descriptor table
shl eax, 4 //segment address eax=ds×16
xor ebx, ebx //clear ebx
mov bx, offset GDT_def //bx=the offset address of GDT_def
add eax,ebx //linear base address of the GDT=eax+ebx
mov dword ptr GDT_Addr, eax //store the linear base address of the GDT into GDT_Addr
lgdt fword ptr GDT_Addr //load GDT_Addr into the GDTR register
mov bx, 8 //set the selector for the data segment descriptor
mov eax, cr0
or al,1
mov cr0,eax //set the PE bit of CR0 = 1
jmp flush1 //enter protected mode
}
flush1: asm{
mov fs,bx //load into FS the data segment descriptor with a 4GB limit
mov gs,bx //load into GS the data segment descriptor with a 4GB limit
and al,0feh
mov cr0,eax //set the PE bit of CR0 = 0
jmp flush2 //return to real mode
}
flush2: asm{
mov ax, 0
mov fs,ax //set the base address of the FS descriptor to 0
mov gs,ax //set the base address of the GS descriptor to 0
sti //enable interrupts
}
}
③Programming example for directly accessing 4GB memory
 After FS and GS have a 4GB access limit, 4GB memory access can be achieved through instructions that use 32-bit register indirect addressing. For example, the computation function for image binarization is as follows:
void two_mem(unsigned long addrd, unsigned long addrs, unsigned long leng,
unsigned char yuzi)
{ asm mov ecx, leng //leng is the byte count of the image data block
asm mov esi, addrs //addrs is the 32-bit linear base address of the source image data block
asm mov edi, addrd //addrd is the 32-bit linear base address of the binarized image data block
asm mov ah, yuzi //yuzi is the threshold
TN0: asm cmp fs:, ah //compare source image data with the threshold
asm mov al, 0 //if the source image data<threshold, al=0
asm jc TN1
asm mov al, 255 //if the source image data≥threshold, al=255
TN1: asm mov fs:, al //store the result into the binarized data block
asm inc esi //increment the 32-bit linear address of the source image data block by one
asm inc edi //increment the 32-bit linear address of the binarized image data block by one
asm loopd TN0
}
④Program structure
void main( )
{ openA20( );
set4gb( );
… … //user program
}

It’s already been two or three months since you made the post, so I don’t know whether this is still of any use ^_^
Forum Jump: