Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

DOS and .COM memory usage

Status
Not open for further replies.

denc4

Programmer
Feb 17, 2005
107
0
0
NL
how does DOS manage the memory usage of a .COM file?

i want more than the standard 64k in a COM file so i started experimenting
with INT21 function 48h and 49h, memory allocation and deallocation respectively.
i used the following code in a COM file to find out the maximum number of
paragraphs (paragraph=16kb?) available to my program:

mov ax,4800h
mov bx,0FFFFh ;request 65535 paragraphs (1.073.725.440 bytes?).
int 21h

the code returns DOS error code 08h (insufficient memory) ofcourse, but in this
case it also returns the maximum available paragraphs. i ran it on various systems
and configurations and found the following returned:

win95 dosbox: 0 paragraphs available
win95 pure dos: 4 paragraphs available
dos 6.22: 4 paragraphs available
win2k dosbox: 7 paragraphs available

i also read somewhere that DOS assigns ALL available memory to a COM file when
it loads. if this is true, then why do the last three configs still return >0
paragraphs available?

or can i just ASSUME that all memory is available to me and ignore function 48h
and 49h all together? (i never use any TSRs so that won't be a problem).

thx.
 
Is there any particular reason you want to go this way instead of using a DOS exe file?
 
i don't get exe files. Where's the PSP in EXEs? i need the PSP.
exe files have 3 segments available to them at load time, if i want more i still have to understand DOS memory allocation.
 
When DOS load a .com file it allogates all memory below
640K to it.
So you first have to free all memory above your program
and then allocate the maximum space.
You have to do this so memory allocated for the extended
bios will not be overwriten.
The amount given by your example is just this space.

A paragraph is 16 bytes long on 16K!!!

succes, Tessa
 
by extended bios, do you mean the resident portion of DOS by that? (when i do a MEM.EXE command in DOS after a clean boot it only displays DOS as resident)
isn't DOS loaded at the beginning of the 640k?

When DOS load a .com file it allogates all memory below
640K to it.

then why does DOS in some of my findings still return
multiple paragraphs that are free?

A paragraph is 16 bytes long on 16K!!!

on what 16K?
don't quite get that sentence.
 
I ment a paragraph is 16 bytes long not 16 kilo bytes.

Since most programmers and books speak of memory as a pile
of byte beginnig at 00000 downto FFFFF I made the mistage
of using this description to a novice.

DOS reserves all memory from the loding point of your
program up to the maximum of 640k, minus the extended bios
data block that is located on the adress 639k in normal
real mode DOS.

If you are running DOS under an other operating system,
memory is allocated in a diferent way.
Since the memory in use by your DOS shell is in fact not
starting at address 00000 at all but can de starting at
00452300h or so something tike that.
And the end of the 640k region may be it bit longer or
even shorter, depending on what to operating system is
using for it memory handling method.

So under realmode DOS you will get the 0 free paragraphs,
under un other operation system you might get the 0 para-
graphs.

Confusing? Yes, but I don't now how to explain it in
short more clearly.

About DOS below loaded at location 00000 the answer is:

- no, there is a interrupt table first, then the DOS and
BIOS data area.

and then, if no upper or high memory is used, DOS will
load its device drivers and then the DOS command shell.

So for now, succes

Tessa

 
yes, 16 bytes makes more sense:

65535 * 16 = 1mb (that's the 80x86 20 line address bus).

your description of different operation systems also makes sense.
i guess the question why the available paragraphs returned are not the same on my
various configurations can only be explained by someone who co-wrote DOS and/or Windows..

those few bytes (7 * 16 on win2k) are negligible anyway..

after your previous post i tried something else.
first i divided my program size with 16, then i fed the result to function 4Ah
(resize memory block). after that subsequent calls to function 48h were succesful.

but i still have a few questions:

when i succesfully allocate LESS than 64kb, function 48h returns the segment number.
because a segment is 64kb in size, i can STILL write to the whole segment!
does DOS take this into consideration?

if, like you said, DOS reserves all memory from the loading point of the program up to the
maximum of 639k, WHY BOTHER with functions 48h, 49h, and 4Ah in .COM files?

hope you can answer them.
thanx so far.
 
The first thing that comes to mind is ...

What if your program needed to load another program (function 4B, I think)?

If you don't have a way to release memory you don't need how and where would your program be able to do that?


[vampire][bat]
 
i am certain that i do not want and do not need to call another program.
if i did have to do it, i would most certainly need to call function 4A or 49 to release some memory.
 
denc4 said:
if, like you said, DOS reserves all memory from the loading point of the program up to the
maximum of 639k, WHY BOTHER with functions 48h, 49h, and 4Ah in .COM files?


I was simply answering your question.

[vampire][bat]
 
From your question:

"when i succesfully allocate LESS than 64kb, function 48h returns the segment number.
because a segment is 64kb in size, i can STILL write to the whole segment!
does DOS take this into consideration?"

I suspect you're misunderstanding DOS memory management and 16-bit addressing. In 16 bit addressing there's no mechanism for remembering how big a segment ought to be, and DOS doesn't even try. DOS is merely in the business of loading a bit of code and transfering control to that code. It manages memory only to the extent of making sure it doesn't put two things in the same place. It doesn't carry out any memory management on behalf of client programs (i.e., don't use it like malloc), and any DOS program is perfectly at liberty to set any value it wants in any segment register, and write anywhere up to 64K from the place pointed to. There's no safety net!

Whether you use a COM file or an EXE file (where the memory required is specified in the header), you are merely dumped in a vacant space and left to get on with your own memory planning. Good luck!

This is one of the main reasons why I prefer to use assembly from within a high-level language such as C or Pascal, to pep-up particular bits of code that need to operate with hardware or at optimal speed, rather than use it for whole programs. The high level languages are really good at memory management.
 
yes earthandfire, i only realised that after i placed my post.
thanx for pointing me to it.

lionelhill.
seems like one got considerable freedoms under DOS.
freedom to destroy memory. :)
if there were any TSRs, and i wanted to, i could completely erase them.

for the time being, i am NOT gonna use DOS memory management functions.
for this to work i need to calculate a new free segment address myself.

new segment = current segment + 0FFFh

i compared it with the results of function 48h and my calculation method seems
to be sound.

function 4A (resize memory block) returns some strange results when
fed the 0FFF value. DEBUG.EXE output on CMD.EXE win2k:

Code:
-R
AX=0000  BX=0000  CX=0321  DX=0000  SP=FFFE  BP=0000  SI=0000  DI=0000
DS=0B3E  ES=0B3E  SS=0B3E  CS=0B3E  IP=0100   NV UP EI PL NZ NA PO NC
0B3E:0100 B8004A        MOV     AX,4A00
-T

AX=4A00  BX=0000  CX=0321  DX=0000  SP=FFFE  BP=0000  SI=0000  DI=0000
DS=0B3E  ES=0B3E  SS=0B3E  CS=0B3E  IP=0103   NV UP EI PL NZ NA PO NC
0B3E:0103 BBFF0F        MOV     BX,0FFF
-T

AX=4A00  BX=0FFF  CX=0321  DX=0000  SP=FFFE  BP=0000  SI=0000  DI=0000
DS=0B3E  ES=0B3E  SS=0B3E  CS=0B3E  IP=0106   NV UP EI PL NZ NA PO NC
0B3E:0106 CD21          INT     21
-P

AX=0B3E  BX=0FFF  CX=0321  DX=0000  SP=FFFE  BP=C100  SI=0000  DI=005A
DS=0B84  ES=0B3E  SS=0B3E  CS=0B3E  IP=0108   NV UP EI PL NZ NA PO NC
0B3E:0108 90            NOP

notice the BP, DI and DS registers. they are destroyed by INT 21..
when i change the BX value to 0FFEh (1 paragraph less), it seems to work
fine.

what's with this one paragraph? any ideas?
 
(1) Yes, in DOS you can happily write over a TSR, and then when it is activated for any reason, everything will (probably) crash...

(2) Int21 returns all the registers in definite states, but not necessarily containing what they had before the call. A good list of DOS calls will tell you what values are returned, and where. There's loads of good lists out there.

Good luck!
 
i have ralph brown's list.
it doesn't say anything about BP, DI, and DS registers being destroyed after a call to function 4Ah with 0FFFh paragraphs in BX.
the fact that it preserves the registers in all other cases is suspicious. not to mention the CMD.EXE crash when i allocate
memory using function 48h after i resized the current segment to 0FFFh paragraphs...

i thought it might have something to do with the PSP, but it being 100h bytes large doesn't explain why function 4Ah still
operates correctly with value 0FFEh and lower in BX.
if it only operated correctly with value 0FEFh and lower in BX it could have explained it..

maybe someday i'll stumble upon the answer.
 
Are you running this under dos or in a dos box under some form of windoze?
 
MSDOS does do some memory handling and checking, not mutch
but it does.

It keeps track of allocated memory true a chain of
allocation tables.

And now the missing one paragraph, taa taa !!!

This is the paragraph holding the information dos needs
to resize and allocate in future calls.
If the chain is broken, MSDOS will just say to it self:

Help I don't now what to do, so it hangs it self up on the
highest tree and dies.

One of the reasons that the link table would show as
corrupted is that there is a back link that has a zero in
it.
If you allocate 0FFFh it put's a backlink of FFFFh+1 into
the link table that would normally marks the end of the
linklist.
Why it put's a zero there is becouse of a small error in
the thinging of the developers of microsofts dos.
Normally the back link is read by getting the backlink into
a index register the segment register will be loaded with
the start of the memory allocated minus 64k, so that the
memory descriptor table for that allocated block is the
last paragraph of the segment.
Then it assumese that the previous descritor is located
at the address given by the segment:index pair.
The descriptor will be checkt for the ascii "Z" (being the
first letter of the last name of the first developer of
MSDOS).
If this is not found, see the HELP above

succes and hopefully did I descripe it a bit clear,

Tessa
 
...and his first name began with an M (hence the MZ markers all over DOS), but I can't remember what his name was. He was involved from DOS 2 (which incorporated the transition from CP/M style OS to something marginally closer to Unix.

Although I think it was Tim Patterson (from Seattle Computers - if memory serves correctly) who wrote the original version of DOS (called QDOS - Quick & Dirty Operating System). He wrote it based almost directly on CP/M, and MS & PC DOS 1 was almost entirely that version (but with some input from IBM and MS)

[vampire][bat]
 
Ok you made me think now very hard, but here the full name
is:

Mark Zbikowski

I look'd it up to write it correctly.

Tessa
 
the 0FEFh paragraphs that i was talking about earlier seems
to be true after all. in the PSP at offset 6 there is a word
that holds the .COM program size: 0FEFh. it is there for
CP/M compatibility.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top