Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to index page
Thread view  Board view
kerravon

Ligao, Free World North,
24.11.2022, 22:47
 

startup rules (Developers)

When an MSDOS .exe or .com starts, I believe it is normal for it to free memory not in use.

I have code below to do that.

The trouble with this is that it hardcodes the number "4" (what segments are shifted by), which is not what I want for the Turbo 186 (8-bit shifts) or PM16 (selectors will be lined up, and a different algorithm is required to adjust "segment" registers).

I can implement an INT 21H extension (I have a bunch of them, under AH=F6h), and I believe MSDOS is designed to set the carry flag if it gets an INT 21H for a function that it doesn't recognize.

So I would like to have a set of functions that manipulate segments. These functions would also be useful when getting Watcom C to generate huge memory model code. It calls external routines like _PIA which does:

; increment address dx:ax by cx:bx, normalized result in dx:ax

(as far as I know).

So what I would like is a global variable (set within the executable's startup code) that determines if the OS has provided an (extended) INT 21H function to manipulate the segment (for PIA) and if so, call that, otherwise, do the "traditional" (in my case about 3 days old) hardcoded 4-bit segment shift.

So nothing is really lost if you are running on a normal 8086 (a quick test of a global variable to see if it is non-zero), but if the (huge memory model) program is running on a Turbo 186 or 80286, the segment manipulation is changed accordingly. And the executable isn't kludged (in my opinion) with detection of the environment and requiring separate code paths and different APIs.

Nor does the MZ executable format need to change.

All that is required is some extended functions, some rules, and traditional MSDOS executables could have accessed up to a theoretical 4 GiB, and on real hardware I think PM32 with the D-bit set to 16-bit will give a maximum of 512 MB before you run out of selectors (using both GDT and LDT). That would be another environment in addition to PM16 and Turbo 186 with 8-bit shifts.

Unless I'm missing something.

Any thoughts?

Thanks. Paul.



; determine how much memory is needed. The stack pointer points
; to the top. Work out what segment that is, then subtract the
; starting segment (the PSP), and you have your answer.

mov ax, sp
mov cl, 4
shr ax, cl ; get sp into pages
mov bx, ss
add ax, bx
add ax, 2 ; safety margin because we've done some pushes etc
mov bx, es
sub ax, bx ; subtract the psp segment

; free initially allocated memory

mov bx, ax
mov ah, 4ah
int 21h

kerravon

Ligao, Free World North,
24.11.2022, 23:04

@ kerravon
 

startup rules

Oh, another thing.

The startup code I currently have doesn't provide for some sort of internal heap (I think that is the correct terminology), so tiny, small and medium memory models can't do a malloc() currently with PDPCLIB, since I rely on MSDOS to satisfy memory requests, which means far data pointers are required.

ecm

Homepage E-mail

Düsseldorf, Germany,
25.11.2022, 08:30

@ kerravon
 

startup rules

> When an MSDOS .exe or .com starts, I believe it is normal for it to free
> memory not in use.

True MZ executables (with the MZ header) can actually specify min alloc and max alloc in their MZ header; DOS will not allocate more memory than specified by the executable image size plus max alloc.

> I can implement an INT 21H extension (I have a bunch of them, under
> AH=F6h), and I believe MSDOS is designed to set the carry flag if it gets
> an INT 21H for a function that it doesn't recognize.

Actually, high functions (including service 71h subfunctions on many versions of DOS) will not set CY to indicate an unsupported function. Instead, they will set al to zero and leave CF unchanged. You can handle this case with an explicit stc before the int 21h in order to make sure you get CY if unsupported.

---
l

kerravon

Ligao, Free World North,
28.11.2022, 23:06

@ ecm
 

startup rules

> > When an MSDOS .exe or .com starts, I believe it is normal for it to free
> > memory not in use.
>
> True MZ executables (with the MZ header) can actually specify min alloc and
> max alloc in their MZ header; DOS will not allocate more memory than
> specified by the executable image size plus max alloc.

I am currently bound by wlink, and I took a look at
one of my programs and see:

DGROUP 0dec:0004 0000bb4c

Memory size: 00019a10 (104976.)

C:\devel\pdos\src>hexdump pcomm.exe 0 50
000000 4D5AF801 8B00F700 40008208 FFFFA118 MZ......@.......
000010 00100000 B8B90000 20000000 00000000 ........ .......

minalloc of 882 - I don't have any idea what this
is for. I assume someone thinks it is a good idea
to max out the 64k addressable by DS.

882H = 2178
2178*16 = 34848
65536-34848 = 30688

The DGROUP portion of "executable size" would presumably
not include bss or stack. But const+data is only 13094 = 3326H

Adding BSS would give 43818 = AB2A. So I have no idea
what the rationale for the minalloc is.

setjmp_TEXT CODE AUTO 0000:de90 00000034
CONST DATA DGROUP 0dec:0004 00002424
CONST2 DATA DGROUP 102e:0008 0000003a
_DATA DATA DGROUP 1033:0000 00000ec8
_BSS BSS DGROUP 1120:0000 00007804
STACK STACK DGROUP 18a1:0000 00001000

And the maxalloc is set to FFFF, and I think Watcom
is not alone in doing that, so DOS will give all
memory regardless.

Rather than patch every executable, or change every
linker, it is probably better to do what I am
already doing which is to resize the memory block
myself. And that covers COM files too.

And regardless, I'm still faced with another place
where I need to hardcode the number 4. In order to
set SS to the same as DS, I need to do this:

mov bx,ss
mov ax,ds
sub bx,ax
mov cl,4
shl bx,cl

mov bp, sp
add bp, bx
mov ss, dx
mov sp, bp

So, since I wish to support the Turbo 186 with
8-bit segment shifts, I need to get rid of that
number 4 and make it flexible. And ideally I would
support a completely different segmentation scheme
for PM16.

So, I need to implement a new INT 21H, and only if
it fails do I resort to the hardcoded 4 above.

Any suggestions?

> > I can implement an INT 21H extension (I have a bunch of them, under
> > AH=F6h), and I believe MSDOS is designed to set the carry flag if it
> gets
> > an INT 21H for a function that it doesn't recognize.
>
> Actually, high functions (including service 71h subfunctions on many
> versions of DOS) will not set CY to indicate an unsupported function.
> Instead, they will set al to zero and leave CF unchanged. You can handle
> this case with an explicit stc before the int 21h in order to make sure you
> get CY if unsupported.

Thanks. I have modified PDOS/86 to start adding
AL=0 support.

BFN. Paul.

DosWorld

29.11.2022, 01:21
(edited by DosWorld, 29.11.2022, 02:28)

@ kerravon
 

startup rules

> I am currently bound by wlink, and I took a look at
> one of my programs and see:
>
> DGROUP 0dec:0004 0000bb4c
>
> Memory size: 00019a10 (104976.)
>
> C:\devel\pdos\src>hexdump pcomm.exe 0 50
> 000000 4D5AF801 8B00F700 40008208 FFFFA118 MZ......@.......
> 000010 00100000 B8B90000 20000000 00000000 ........ .......
>
> minalloc of 882 - I don't have any idea what this
> is for. I assume someone thinks it is a good idea
> to max out the 64k addressable by DS.

(Sorry, may be i am will write the same as you say, - i am not so good known about segment groups in obj/omf, i try live in rdf without this hell :-D , so i am skip some parts)

This is NOT one segment. This is memory can be:

1. Stack segment. IMHO, SS:SP (exe header fields) must point to this area.
2. Multiple bss segments. How to deal with it - this .exe problem and dos don't worry. (exe deal with it via relocation records and this is pain for compiler/linker).
3. Memory available for malloc/free. I don't investigate TC, but 99% it is true for TP and 80% for WC.

How to mean "min memory" and "max memory" into exe:
min memory = stack + all bss + min memory available for malloc/free
max memory = stack + all bss + max memory available for malloc/free

In this memory model, malloc/free (or pascal's getmem/freemem) don't call INT21 to (de)allocate memory. malloc/free have sandbox which full allocated at start and FULL unallocated at end.
So, if program have memory leaks - it will be more safe (then work with INT21).

Bad idea put FFFF to maxmem by default - it cause problem if need run another exe from your program. (i fight with it into make - Exesize-workaround)

I don't known how to change min/max mem values for C compilers/linkers and how it calculates. TP is more flexible and have compiler directive:

{$M stackSizeBytes,minMemoryBytes,maxMemoryBytes}

for example:

{$M 10240,128000,650000}

---
Make DOS great again!

Carthago delenda est, Ceterum censeo Carthaginem delendam esse.

kerravon

Ligao, Free World North,
29.11.2022, 02:24

@ DosWorld
 

startup rules

> How to mean "min memory" and "max memory" into exe:
> min memory = stack + all bss + min memory available for malloc/free

Ah! Thankyou. Now the numbers finally add up.

BSS is 7804H (30724), stack is 1000H (4096),
meaning I need:

(30724+4096)/16 = 2176.25 paragraphs, ie 2177
paragraphs, ie 881H, ie:

C:\devel\pdos\src>hexdump pcomm.exe 10 2
00000A 8208 ..

close enough to 882H

BFN. Paul.

DosWorld

29.11.2022, 03:03

@ kerravon
 

startup rules

> Now the numbers finally add up.

Yep. If you can't provide allocated minmem memory - feel free don't start a program (because it required). maxmem - is more optional.

---
Make DOS great again!

Carthago delenda est, Ceterum censeo Carthaginem delendam esse.

Back to index page
Thread view  Board view
22049 Postings in 2034 Threads, 396 registered users, 79 users online (0 registered, 79 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum