1. Computer problem? Tech Support Guy is completely free -- paid for by advertisers and donations. Click here to join today! If you're new to Tech Support Guy, we highly recommend that you visit our Guide for New Members.

Solved: Combine two programs into one image

Discussion in 'Software Development' started by mt2002, Oct 12, 2008.

Thread Status:
Not open for further replies.
Advertisement
  1. mt2002

    mt2002 Thread Starter

    Joined:
    Sep 14, 2005
    Messages:
    919
    Hey everyone,

    This is for my software project so I decided to post it here. I am looking for a program (preferably command line for Windows) that can combine two programs into a single image.

    By "combine", I mean to merge two programs into a single image so the end result of the image is as so:

    Code:
    Single image file------
    [Program 1][Program 2]
    Program 1 is a binary 16 bit / 32 bit assembly language program and Program 2 is a 32 bit C++ program, both running in supervisor mode. There are several reasons why I need this. Im having some trouble finding this on Google so if anyone has any links that would be great :D

    I suppose if we cant find any I can always write it myself... ;)

    Thanks for any help :)
     
  2. -Fabez-

    -Fabez-

    Joined:
    Jul 28, 2008
    Messages:
    1,899
    Do you want them to be executable from the merged file or do they just have to be merged into one file ?
     
  3. lotuseclat79

    lotuseclat79

    Joined:
    Sep 12, 2003
    Messages:
    20,583
    Hi mt2002,

    Have you thought about doing/trying the following:
    Create a new c++ program that has one input parameter that can take the form of two values, e.g. 0, 1.

    Case the parameters, and
    0) switches to the assembler code done in-line, and
    1) switches to the c++ coded program.

    -- Tom
     
  4. mt2002

    mt2002 Thread Starter

    Joined:
    Sep 14, 2005
    Messages:
    919
    Didnt know I would get responses so I decided to make it myself :) It was easier then I thought :D

    The merged file would be executable. This is why I needed the binary program to be the first program inside of the file--it contains the instructions to set up the system and run the MSVC++ program.

    Thats a cool idea but wont work in this case as I need both programs. The first program calls the second, and the second program relies on the first program. (The first program contains code that the MSVC++ program cannot do. Thus, to do those functions the MSVC++ program calls the first program).

    Its not complete yet, but seems to be working so far. Heres the program in case anyone is interested:

    *edit: I added comments for anyone who is interested :)

    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    
    //! program name
    const std::string _strProgName = "merge.exe";
    
    //! program interface
    class prog {
    
    	std::fstream	m_fOut;
    	void display_parm_help ();
    
    public:
    
    	bool init (std::string& fIn);
    	int run (int argc, char** argv);
    	virtual ~prog ();
    };
    
    //! display help info if incorrect command line is used
    void prog::display_parm_help () {
    
    	std::cout << "Incorrect command line syntax" << std::endl;
    	std::cout << "Syntax: " << _strProgName << " output_file file1 file2 file_n" << std::endl;
    }
    
    //! inits the program
    //! in/ fIn - filename of output file to work with
    bool prog::init (std::string& fIn) {
    
    	//! open up the file in binary mode (and cleared out), create it if its not there
    	m_fOut.open(fIn.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); 
    
    	//! if file is not open, there was an error, bail out
    	if (!m_fOut.is_open ()) {
    
    		std::cout << "Unable to open output file \'" << fIn << "\', aborting..." << std::endl;
    		return false;
    	}
    
    	return true;
    }
    
    //! dtor called at program exit
    prog::~prog () {
    
    	//! close the output file if its still open
    	if (m_fOut.is_open ())
    		m_fOut.close ();
    }
    
    //! main program core
    int prog::run (int argc, char **argv) {
    
    	//! argc containes number of command line paramaters passed.
    	//! this program requires at least 4: program_name.exe, outfile, file1 and file2
    	if (argc < 4) {
    
    		//! its not, so bail out
    		display_parm_help ();
    		return 1;
    	}
    
    	//! paramater 1=output file name
    	std::string str (argv[1]);
    
    	//! initialize the program w/ the output file name. If fails return error
    	if (!init (str))
    		return 1;
    
    	//! stores number of bytes written to output file
    	int outLength = 0;
    
    	//! for all of the input files in the paramater list...
    	for (int i=2; i<argc; i++) {
    
    		std::cout << "Merging file '" << argv[i] << "'..." << std::endl;
    
    		//! open the file in binary mode
    		std::fstream fIn (const_cast <char*> (argv[i]), std::ios_base::in | std::ios_base::binary);
    
    		//! get size of file in bytes, store in length
    		fIn.seekg (0, std::ios::end);
    		int length = fIn.tellg();
    		fIn.seekg (0, std::ios::beg);
    
    		//! read the file into buffer
    		char* buffer = new char [length];
    		fIn.read (buffer, length);
    
    		//! ...and write the buffer to the output file
    		m_fOut.write (buffer, length);
    
    		//! add number of bytes written and cleanup
    		outLength+=length;
    		delete [] buffer;
    		fIn.close ();
    	}
    
    	std::cout << outLength << " bytes written to " << argv[1] << ", completed" << std::endl;
    
    	return 0;
    }
    
    int main (int argc, char** argv) {
    
    	//! just run the program passing in the command line paramamters
    	prog merger;
    	return merger.run (argc, argv);
    }
    To use it, just run it from command line like merge.exe outputfile.bin prog1.sys prog2.exe prog3.exe etc... It simply merges all files into outputfile.sys one after the other.
     
  5. -Fabez-

    -Fabez-

    Joined:
    Jul 28, 2008
    Messages:
    1,899
    I'm interested in how this works, could you take some time to comment it please ? C++ has never been my strongpoint :D
     
  6. mt2002

    mt2002 Thread Starter

    Joined:
    Sep 14, 2005
    Messages:
    919
    I added some comments :) I cant explain how the image itself works though (Well, I *can*, but its a bit complex)

    Hope this helps out a little :D
     
  7. -Fabez-

    -Fabez-

    Joined:
    Jul 28, 2008
    Messages:
    1,899
    Thanks for the comments, I shall read through the code now, thanks :D
     
  8. -Fabez-

    -Fabez-

    Joined:
    Jul 28, 2008
    Messages:
    1,899
    I have read through your comments and just wanted to make sure I get them, so can I ask you some questions about the code and the finished file please ?
     
  9. mt2002

    mt2002 Thread Starter

    Joined:
    Sep 14, 2005
    Messages:
    919
    Go for it :)
     
  10. pvc_

    pvc_

    Joined:
    Feb 17, 2008
    Messages:
    490
    does this run both applications at the same time? because it seems like it just reads two programs and writes them back to back. To run them, you'll have to separate the two.
     
  11. mt2002

    mt2002 Thread Starter

    Joined:
    Sep 14, 2005
    Messages:
    919
    Neither--the image itself runs as a single program.

    The image works do to the way they are written. ie; the first program runs the 2nd program directly after the image is loaded into memory. --They are not treated as separate programs but rather a complete image.

    I should add that this was for my systems bootloader which is composed of two programs and is self hosted. I can add more details of how the image works if you are interested.

    If they were both PE executables (or similar) this may not work as a single image though--Im not too sure...It works fine for what I need though.
     
  12. -Fabez-

    -Fabez-

    Joined:
    Jul 28, 2008
    Messages:
    1,899
    Thanks for taking the time to answer some questions :D

    1) Can the both programs see each other E.g. The first one can call the second one and the second one can call the first one ?

    2) Does it work with two Windows .Exe's ?

    3) Does the second .Exe automatically execute after the first .Exe terminates or ends ?
     
  13. mt2002

    mt2002 Thread Starter

    Joined:
    Sep 14, 2005
    Messages:
    919
    Are these questions in relation to my software or any software? I have only used it for my software which I personally dont consider a normal case.

    In my software, yes. I believe it should be possible with any software though as its treated as a single file by the host operating system or executive.

    It should. Will it run depends on how you jump between the two programs within the code and if Windows loads it as a flat binary file or a PE executable.

    If the 1st program is loaded as a flat binary, you may need to use assembly language. If its loaded as a PE executable it should work fine.

    An easy way of testing is doing it the way I do it: Parse the 2nd programs header information by referencing the memory right after the 1st program in memory and call its entry point of the 2nd program from the 1st. I can show you my code for an example but keep in mind its in assembly.

    It would be interesting to see what happens here though :)

    What do you mean by "execute"? Technically the 2nd program file is directly after the first in memory, but this also includes all header information and so on as well..

    The 1st program would need to parse the header info of the 2nd program (See previous question) in order to obtain the entry point address of the 2nd program and execute it.
     
  14. pvc_

    pvc_

    Joined:
    Feb 17, 2008
    Messages:
    490
  15. mt2002

    mt2002 Thread Starter

    Joined:
    Sep 14, 2005
    Messages:
    919
    Its simply a manner of parsing the 2nd programs header info to obtain the entry point address to call it. Assuming it is merged with the 1st program, and the 1st program is flat binary, this is relatively easy (It did require 3 rewrites of execute_loader() though..hehe)

    I added some extra comments to help clarify some things. execute_loader() is what I am currently using to execute the 2nd program, which is a PE executable that I merged with merge.exe. I also took out some other irrelevant code that my system uses to pass information to the 2nd program.

    Code:
    execute_loader:
    
    	; STARTUP_SYS_END is the address of the end of 1st program
    	; and is the address of the 1st byte in second program
    
    	; you dont need to load the second program as its already in memory
    	; right after us
    
    	; get file sig (PE00) of second program, store in ebx
    
      	mov	ebx, [STARTUP_SYS_END+60]
    	add	ebx, STARTUP_SYS_END
    
    	; get entry point offset in code section
    
    	add	ebx, 24
    	mov	eax, [ebx]		; _IMAGE_FILE_HEADER is 20 bytes + size of sig (4 bytes)
    	add	ebx, 16			; address of entry point
    	mov	ebp, dword [ebx]	; get entry point offset in code section
    
    	; add image base
    
    	add	ebx, 12			; image base is offset 8 bytes from entry point
    	mov	eax, dword [ebx]	; add image base
    	mov	edi, eax
    	add	ebp, eax
    
    	; get size of image in bytes
    
    	add	ebx, 28			; size of image offset 24 bytes from image base
    	mov	eax, [ebx]
    
    	; copy the program to the address it exepects to be at
    	; iirc this is in MSVC++ linker settings->advanced->base address
    
    	cld
    	mov	esi, STARTUP_SYS_END
    	mov	ecx, eax
    	rep	movsd
    
    	; call entry point of 2nd program
    
    	cli
    	call	ebp			; Execute osloader
    
    	; halt system if 2nd program returns
    
    	cli
    	hlt
    Ill post the PE file header structures a little later if you need them.
     
  16. Sponsor

As Seen On
As Seen On...

Welcome to Tech Support Guy!

Are you looking for the solution to your computer problem? Join our site today to ask your question. This site is completely free -- paid for by advertisers and donations.

If you're not already familiar with forums, watch our Welcome Guide to get started.

Join over 733,556 other people just like you!

Thread Status:
Not open for further replies.

Short URL to this thread: https://techguy.org/758589

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice