Search code examples
windowsgccassemblyx86nasm

Assembly 32-bit - Calling a program from another program


I'm currently learning Assembly, I'm not very new but maybe since 1 - 2 months back. I am using 32-bit Assembly, NASM to assemble it into a .o file and MinGW/gcc to compile to a .exe file. but It takes so much time to type "nasm -f elf " in the nasm directory and then do "gcc -o " all the time. so I wanted to create a quick program where I just start it. and all that gets executed.

So I want the program to 1st start the nasm assembler. then wait till it's done (like when you call another function), and after that, I want to start the gcc compiler, and wait till that is done. I know it's quite easy to make in batch files, but I still want to learn how to do it in assembly, incase I need to do it someday. So the question is, how do I start a program (with start/console parameters), and then also wait for it to exit.

Thanks!


Solution

  • You can start a program with CreateProcessA and wait for its end with WaitForSingleObject. The GCC-linker (LD) needs also a suffix with the number of the pushed bytes (e.g. "@4", one dword = four bytes). That is one reason to use another linker.

    Here's a simple example to start a shell (cmd.exe) with a "dir"-command:

    exec_dir.asm:

    STRUC _STARTUPINFO                      ; https://msdn.microsoft.com/library/windows/desktop/ms686331.aspx
        .cb:                resd 1
        .lpReserved:        resd 1
        .lpDesktop:         resd 1
        .lpTitle:           resd 1
        .dwX:               resd 1
        .dwY:               resd 1
        .dwXSize:           resd 1
        .dwYSize:           resd 1
        .dwXCountChars:     resd 1
        .dwYCountChars:     resd 1
        .dwFillAttribute:   resd 1
        .dwFlags:           resd 1
        .wShowWindow:       resw 1
        .cbReserved2:       resw 1
        .lpReserved2:       resd 1
        .hStdInput:         resd 1
        .hStdOutput:        resd 1
        .hStdError:         resd 1
    ENDSTRUC
    
    STRUC _PROCESS_INFORMATION              ; https://msdn.microsoft.com/library/windows/desktop/ms684873.aspx
        .hProcess:      resd 1
        .hThread:       resd 1
        .dwProcessId:   resd 1
        .dwThreadId:    resd 1
    ENDSTRUC
    
    section .data
        startupinfo:
            istruc _STARTUPINFO
            iend
        procinfo:
            istruc _PROCESS_INFORMATION
            iend
        app_fullpath: db "C:\Windows\System32\cmd.exe",0
        params: db "/c dir", 0
        msg: db `\n\nok.\n`,0
    
    global _main
    EXTERN _ExitProcess@4, _CreateProcessA@40,_WaitForSingleObject@8
    EXTERN _puts, _fflush
    
    section .text
    _main:
    
        ; CreateProcess(app_fullpath,params,0,0,false,0,0,0,&startupinfo,&procinfo)
        push procinfo
        push startupinfo
        push 0
        push 0
        push 0
        push 0
        push 0
        push 0
        push params
        push app_fullpath
        call _CreateProcessA@40         ; https://msdn.microsoft.com/library/windows/desktop/ms682425.aspx
    
        ; WaitForSingleObject( procinfo.hProcess, INFINITE );
        push -1         ; INFINITE
        push dword [procinfo + _PROCESS_INFORMATION.hProcess]
        call _WaitForSingleObject@8
    
        ; puts ("ok."), fflush to flush the stdout-buffer
        push msg
        call _puts
        mov dword [esp], 0
        call _fflush
        add esp, 4
    
        ; return 0
        push 0
        call _ExitProcess@4
    

    In a (Windows) Command Prompt:

    PATH C:\MinGW\bin;<Path\to\nasm.exe>
    nasm.exe -fwin32 exec_dir.asm
    gcc.exe -m32 -o exec_dir.exe exec_dir.obj
    exec_dir.exe