Hi,
I'm trying to find the entry point of a 16-bit program's .exe file, without opening it with a tool like TD.
I found the IP in the 21st byte, but couldn't find the CS.
I suspect it might be dynamic, and that CS is set only when the program is loaded onto the memory, but I want to be on the safe side before I do crazy things.
Thanks,
Rogare.
> I suspect it might be dynamic, and that CS is set only when the program is loaded onto the memory
Yes, the MZ header contains CS:IP, the value for CS is relocatable, so it is a paragraph offset from the PSP, same for SS:SP.
Thanks!
Another sort-of related question.
I have a .asm file which ends with:
__start: int 3h
__table db 01h
dw seg nullsetup, offset nullsetup
end __start
I assemble the file, and give the result to my other .exe file as a command line argument.
I want this file to open the first .exe (using int 21h/3Dh) and then to execute "nullsetup".
How can I do that?
Quote from: Rogare on September 17, 2010, 12:46:17 PM
Thanks!
Another sort-of related question.
I have a .asm file which ends with:
__start: int 3h
__table db 01h
dw seg nullsetup, offset nullsetup
end __start
I assemble the file, and give the result to my other .exe file as a command line argument.
I want this file to open the first .exe (using int 21h/3Dh) and then to execute "nullsetup".
How can I do that?
Hi,
The normal way to execute/run a child program is
through the use of Fn 4BH subfunction 0 (AX = 04B00H).
You create a "LOADEXEC" structure, point DS:DX to a
string containing the filename, point ES:BX to the structure,
and execute Int 21H/4BH.
Fn 3DH is the "open file with handle" function. You could
then read a *.COM file into your memory, and execute it.
But that has problems with program termination. To run
an *.EXE file you would have to write a relocating loader to
do what MS-DOS does to load and run the file.
HTH,
Steve
Thanks for your reply!
Umm... I see that 21/4B01 is Load but do not execute, could I do that as well? I just want to call some of the procedures in the file, not run it.
I could put a call for an interrupt in the file and hook this interrupt, but seems a bit patchy (maybe it isn't - my experience with advanced ASM programming is limited).
Hi,
Quote from: Rogare on September 22, 2010, 03:53:09 PM
Thanks for your reply!
You're welcome.
Quote
Umm... I see that 21/4B01 is Load but do not execute, could I do that as well? I just want to call some of the procedures in the file, not run it.
Well, probably. It would depend on what the program does
to initialize things and the program flow. If you know enough
about the routines to use them, why not include them in your
program? I guess the easiest way to find out is to try it out.
Quote
I could put a call for an interrupt in the file and hook this interrupt, but seems a bit patchy (maybe it isn't - my experience with advanced ASM programming is limited).
Not sure what you mean here. Run the program with your
program as a shell or TSR and try to gain control? That could
work, I used a TSR to fix a Y2K problem for instance. But for
realistic control, this looks poor. And the Microsoft programmer's
reference says some things in the discussion of Int 21H / 4B05H,
set execution state, that sounds like the system may be in a
fragile state if you try almost anything useful with an interrupted
program.
Regards,
Steve N.
Quote from: FORTRANS on September 22, 2010, 04:47:01 PM
Quote
Umm... I see that 21/4B01 is Load but do not execute, could I do that as well? I just want to call some of the procedures in the file, not run it.
Well, probably. It would depend on what the program does
to initialize things and the program flow. If you know enough
about the routines to use them, why not include them in your
program? I guess the easiest way to find out is to try it out.
This is a program I wrote, I know it well. Cannot include because I need dynamic linking (on each run I use a different version of the file, and I don't want to re-assemble whenever I write a new version - waste of both time and space).
Hi,
Okay, what you are doing in essence is loading code as an
overlay to get your different versions. You should be good to go.
You might try the Int 21h/4B03H load overlay.
Regards,
Steve N.
Do you know any examples?
I got no idea what to do after the interrupt call (of 21/4B03).
Hi,
Amusing. I tried to create an example using a Fn 4B03
call. If I try to load a non-existant file I get an error (carry
flag set). If I try to load a real file (.OBJ, .EXE, or .COM)
I get no error, but nothing is loaded. At least not where I
asked it to load. (A small file into my data segment.) Any
comments guys?
In a Waite Group book "MS-DOS Developer's Guide" there
is a paragraph on using LINK to create overlays. No real
discussion on any preparation though. And trying the standard
random programming techniques locked up the computer.
In my PowerStation FORTRAN documentation there is a
mention of overlays in the index, but nothing in the text. In
my DOS 3.0 and associated Programmer's Utility Pack
documentation, there is a discussion of "overlay manager"
overlays in the LINK.EXE sections. First attempts along
those lines are in progress. So far requires using LINK and
LIB (from MASM 5.0 for now) to work anything at all. The
program created is different from a standard program
without the extra command line LINK stuff.
Oh well, more amusement ahead I guess. If I get it to
work I may work up an example to post. Something fishy
going on in LINK so far.
Cheers,
Steve N.
Edit: Corrected a document reference. Also the LINK from
MASM 5.0 just supressed error messages and did not work
in any case. See later post.
SRN
i suspect some of the mechanisms to handle DOS overlays are absent in newer OS's
so - not sure it's worth too much effort to learn it - lol
but, if i wanted to figure it out....
.... i would take some old program that uses overlays and see how it was put together
Most DOS linkers defaulted to allocating all of free DOS space on startup, so one of the things you needed to do before loading a second program was to release some memory first. Or you could just set the linker up to allocate the minimum required memory space.
good point, tenkey
as i recall, .COM programs own all the memory up to the 640K boundry, so you must free some first
.EXE programs own all that is required to accomodate the code, data, and stack space specified in the EXE header
i think there is a DOS function you can call to see how much is available (don't remember - lol)
if not, you can chase the heap allocation header blocks (paragraphs) to the end of 640K
Quote from: dedndave on September 23, 2010, 02:40:12 PM
i suspect some of the mechanisms to handle DOS overlays are absent in newer OS's
No - because the mechanisms are all supplied by the executable. You told the linker that you want overlays and then it added a module - the "overlay manager" - during the link step to your object modules, which later, at runtime, did the work required to manage overlays.
The MS "overlay manager", included by the MS OMF linker, replaced all far calls into other overlays by code sequence CD 3F XX OOOO ( INT 3Fh, followed by "overlay number" XX, and then the 2 byte offset within the overlay).
The overlays the linker generates are placed in the same EXE, each has it's own MZ header and code.
The syntax for the 16-bit linker went something like this,
LINK /SEG:250 /NOE /STACK:8000 main.obj (thing1.obj) (thing2.obj) bit1.obj (thing3.obj) (thing4a.obj thing4b.obj thing4c.obj),main.exe,main.map,lib1.lib lib2.lib,
It figure things out automatically, and made a hole in memory big enough to pull in each individual overlay (ie big enough to hold the largest footprint).
Most of it was invisible. There are a couple of examples for using 4B03h in the context of loading device drivers from the command line.
An example of using 4B03h to load another EXE, written from scratch
TESTAPP.ASM
; DOS Overlay example
; testapp.asm
; Built thusly
; \masm32\bin\ml -c -Fl testapp.asm
; \masm32\bin\link16 testapp.obj,testapp,testapp,,,
; Using classical segment definitions for finer control of alignment and ordering
_TEXT segment para use16 public 'CODE'
_TEXT ends
_DATA segment word use16 public 'DATA'
_DATA ends
STACK segment para use16 stack 'STACK'
STACK ends
_OVLY segment para use16 public 'DATA' ; Paragraph alignment is important
_OVLY ends
DGROUP group _DATA,STACK
STACK segment
db 512 dup (?)
STACK ends
_OVLY segment
overlay db 32768 dup (?) ; Allocating space to load overlay EXE
_OVLY ends
_DATA segment
file db "testovl.exe",0 ; Overlay EXE name
param dw seg _OVLY ; Load Segment, basically the space at buffer
dw seg _OVLY ; Relocation Factor
msg1 db "Running testapp.asm", 10, 13, "$"
msg2 db "Leaving testapp.asm", 10, 13, "$"
msgfail db "Loading overlay failed", 10, 13, "$"
_DATA ends
_TEXT segment
_start:
mov ax,DGROUP
mov ds,ax
mov es,ax
mov dx,offset msg1
mov ah,09h ; Print String
int 21h
mov dx,offset file ; ds:dx
mov bx,offset param ; es:bx
mov ax,4B03h ; Load Overlay
int 21h
jc _fail
call far ptr overlay
mov dx,offset msg2
mov ah,09h ; Print String
int 21h
_exit:
mov ax,4C00h ; Quit
int 21h
_fail:
mov dx,offset msgfail
mov ah,09h ; Print String
int 21h
jmp _exit
_TEXT ends
end _start
TESTOVL.ASM
; DOS Overlay example
; testovl.asm
; Built thusly
; \masm32\bin\ml -c -Fl testovl.asm
; \masm32\bin\link16 testovl.obj,testovl,testovl,,,
.MODEL MEDIUM
.STACK 512 ; Uses the caller's stack, but this stops the linker griping
.DATA
msg db "From the overlay",10,13,'$'
.CODE
_start: ; Entry point assumed to be _TEXT:0
push ds ; Save DS,ES of caller
push es
mov ax,@DATA ; Data segmentation for overlay
mov ds,ax
mov es,ax
mov dx,offset msg
mov ah,09h ; Print string
int 21h
pop ds ; Restore DS,ES of caller
pop es
retf ; Far return back to calling app
END _start
Run
C:\MASM>testapp
Running testapp.asm
From the overlay
Leaving testapp.asm
C:\MASM>
If you needed entry points for the EXE, I think you'd need to load the header manually and examine it. To handle bigger, random sized, EXE files you would again need to examine the header and dynamically allocate enough space for the image (minimum load size). If you used EXEPACK on the overlay, you'd need to call into it to have it unpack itself.
The attachment contains another example where the main app and the overlay are both EXEs, the overlay is loaded into allocated memory with the Load Overlay function, and the main app calls procedures in the overlay through a jump table. I included code that shows what the segment structure of the main app is, and what is going on at a memory block level. My command lines were:
ml /Fl /Sa /c filename.asm
link16 /MAP filename.obj
In my example I did not attempt to access the overlay's data segment from the overlay procedures. To do this you would need to preserve the caller's DS, load the segment address of the overlay's data segment into DS, do the access, then restore the caller's DS, for example:
push ds
mov ax, SEG xxx
mov ds, ax
mov dx, xxx
pop ds
Hi,
Thanks to clive and MichaelW for the examples. I got my code
to work with the load overlay function 4B03. Paragraph aligned
the overlay load area and changed the loRelocationFactor value.
A question to japheth or clive; is there a way to obtain the
required .LIB or .OBJ to get the Overlay Manager to work? Or to
recognize it among the various files/programs I own?
LINK : error L2048: Microsoft Overlay Manager module not found
Quotei think there is a DOS function you can call to see how much is available (don't remember - lol)
You try and allocate a lot of memory and check how much
you got. Crude and rude. The PSP also holds a value that is
the size of the memory owned by the program.
Quoteif not, you can chase the heap allocation header blocks (paragraphs) to the end of 640K
Walking the memory control block (MCB or ARENA) chain will
tell you the size and what owns each block of allocated memory,
and if there is any left unallocated. Seems to be a popular exercise
in some of the books I have.
Regards,
Steve N.
Quote from: FORTRANS
A question to japheth or clive; is there a way to obtain the
required .LIB or .OBJ to get the Overlay Manager to work? Or to
recognize it among the various files/programs I own?
LINK : error L2048: Microsoft Overlay Manager module not found
I'm looking at MSC 7.00, there is overlay code in CLIBC7.LIB which came from dos\ovlm6l.asm, also CLIBCE.LIB,LLIBC7/CE.LIB,MLIBC7/CE.LIB,SLIBC7/CE.LIB
The overlay manager is probably in MOVETR.LIB (\src\move.lib)
LINK.EXE 5.30.051
In \C700\SOURCE\MOVE is the source for the overlay manager.
From MOVEAPI.TXT
MOVEAPI.TXT File
Release Notes for the
Microsoft(R) Overlay Virtual Environment
Released with the Microsoft(R) C
Professional Development System, Version 7.0
(C) Copyright Microsoft Corporation, 1991
This document describes advanced features of the Microsoft Overlay
Virtual Environment (MOVE). MOVE is a dynamic overlay manager
for use in creating DOS programs with overlays. MOVE is described
in the chapter called "Creating Overlaid DOS Programs" in the
"Environment and Tools" manual. This file discusses ways you can
customize your overlaid program and analyze its performance.
Segments to look for OVERLAY_THUNKS, _MOVETEXT, MOVEINIT_TEXT, OVERLAY_DATA
0087 - Typ:0120 sstModule Mod:0031 Off:000092AC Len:00000024
11.00000000[00001006]
..\src\move.asm
0088 - Typ:0123 sstPublicSym Mod:0031 Off:000092D0 Len:000001E8
Size 000001E4
00000004: 0015 0103 S_PUB16 0000 11.0F16 -> 0BEC.00000F16 __movefpause
0000001B: 0015 0103 S_PUB16 0000 11.0F59 -> 0BEC.00000F59 __moveresume
00000032: 0016 0103 S_PUB16 0000 11.0CCA -> 0BEC.00000CCA __movesetheap
0000004A: 0015 0103 S_PUB16 0000 11.0CA5 -> 0BEC.00000CA5 __movegetmem
00000061: 0016 0103 S_PUB16 0000 11.0F18 -> 0BEC.00000F18 __movefpaused
00000079: 0016 0103 S_PUB16 0000 11.0F9B -> 0BEC.00000F9B ___lpfncvhook
00000091: 0013 0103 S_PUB16 0000 11.0BE5 -> 0BEC.00000BE5 $$MOVEINIT
000000A6: 0017 0103 S_PUB16 0000 11.0DD4 -> 0BEC.00000DD4 __movesetcache
000000BF: 0016 0103 S_PUB16 0000 11.0135 -> 0BEC.00000135 ___move_stack
000000D7: 001D 0103 S_PUB16 0000 11.0013 -> 0BEC.00000013 ___move_seg_ovltable
000000F6: 0014 0103 S_PUB16 0000 11.0B8F -> 0BEC.00000B8F ___move_ret
0000010C: 0014 0103 S_PUB16 0000 11.0F1E -> 0BEC.00000F1E __movepause
00000122: 001A 0103 S_PUB16 0000 11.02B7 -> 0BEC.000002B7 ___move_terminate
0000013E: 0015 0103 S_PUB16 0000 11.0027 -> 0BEC.00000027 __moveckbxms
00000155: 001A 0103 S_PUB16 0000 11.02B5 -> 0BEC.000002B5 ___move_stack_ptr
00000171: 0015 0103 S_PUB16 0000 11.0007 -> 0BEC.00000007 __movesegenv
00000188: 0017 0103 S_PUB16 0000 11.0017 -> 0BEC.00000017 ___move_ovlcur
000001A1: 0017 0103 S_PUB16 0000 11.0DAF -> 0BEC.00000DAF __movegetcache
000001BA: 0015 0103 S_PUB16 0000 11.0025 -> 0BEC.00000025 __moveckbems
000001D1: 0015 0103 S_PUB16 0000 11.0950 -> 0BEC.00000950 ___move_load
00E1 - Typ:0120 sstModule Mod:005E Off:0000A1AD Len:00000026
12.00000000[000001A2]
..\src\moveinit.c
00E2 - Typ:0123 sstPublicSym Mod:005E Off:0000A1D4 Len:00000019
Size 00000015
00000004: 0013 0103 S_PUB16 0000 12.0000 -> 0CEC.00000006 __moveinit
Hi,
Thank you. Unfortunately not a product I have. As the
other way works, I guess not a big deal. Especially as I
have no real need for overlays. But it did look like a much
easier/convenient way of doing things.
Thanks,
Steve N.
Quote from: FORTRANS
Thank you. Unfortunately not a product I have. As the other way works, I guess not a big deal. Especially as I have no real need for overlays. But it did look like a much easier/convenient way of doing things.
I have PDS (Basic) 7.0 and 7.1 but haven't dug into them much. The MSC 7.0 project is one, of several, that I inherited from the early 90's that used overlays. It seems to work in a simple/painless way, binding them into a single EXE with multiple MZ headers, but you'd have to cluster common functions together for it to be remotely efficient. The projects look to park initialization code, and then different menus and code flow into their own overlays. Personally, I preferred just to use 16 and 32-bit DOS extenders to manage monster projects, or use DOS/EMS for large data structures.
Hi,
That makes sense. Overlays seem to be a last ditch
effort kind of thing. I think that early on some of the
larger FORTRAN programs I had to use were overlayed.
Never wrote one though. The computers seemed to cope
with things better fairly quickly. So by the time I wrote
larger programs they could be all in one unit. So this little
exercise turned out to be fairly interesting.
Cheers,
Steve N.