Results 1 to 7 of 7

Thread: call a program

  1. #1

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197

    call a program

    how do I call a program written in c++?
    retired member. Thanks for everything

  2. #2

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197
    BUMP
    even though this forum is so slow its still near the top...
    retired member. Thanks for everything

  3. #3
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    call?
    That depends on your OS. If you use MASM and Windows you can call CreateProcess or ShellExecute

    linux or dos you might want to import the CRT _exec function family

    Or do you want to call a function???
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  4. #4
    PowerPoster abdul's Avatar
    Join Date
    Dec 2000
    Location
    Ontario,Canada
    Posts
    2,827
    Well, if you want to call a function, you have to first compile your C code to an object file. C++ code won't work because the compile mangles the functions unless you specifically tell the compiler to mangle the functions in C style (puts an underscore in front of the function).
    Now you have to assemble your assembly code using the object file in the command file options of the assembler. Let's say if you have a function called "main" in your C code, you call the function in assembly using this:
    PHP Code:
    call _main 
    You might have to declare _main as an external variable like this:
    PHP Code:
    extern _main ;Goes under segment .text 
    The above will work if your function takes no arguements (void). In order to a function that takes some arguments, you have to push all the arguments onto the stack (the last parameter is pushed first and so on...). Here's an example which uses the "printf" function from some C object file:
    Code:
    segment .data
    
    format db "Hello!  This is number is: %d", 0
    number dd 5 ;just an extra parameter
    push dword [number] ;Push the value of number - not the 
    address
    
    segment .text
    
    push dword format ;Push the address of format
    call _printf ;Call the function
    ;...Remove the parameters from that stack
    add esp, 8 ;Moves the stack pointer up 8 bytes
    For stdcall or cdec(sp?) (can't remember which one), you may not have to remove the parameters from the stack. The function will automatically do so.
    Baaaaaaaaah

  5. #5
    PowerPoster abdul's Avatar
    Join Date
    Dec 2000
    Location
    Ontario,Canada
    Posts
    2,827
    Here's some more good info on calling C functions...got for NASM documentation:
    The C calling conventionThe C calling convention in 32-bit programs is as follows. In the following description, the words caller and callee are used to denote the function doing the calling and the function which gets called.

    The caller pushes the function's parameters on the stack, one after another, in reverse order (right to left, so that the first argument specified to the function is pushed last).
    The caller then executes a near CALL instruction to pass control to the callee.
    The callee receives control, and typically (although this is not actually necessary, in functions which do not need to access their parameters) starts by saving the value of ESP in EBP so as to be able to use EBP as a base pointer to find its parameters on the stack. However, the caller was probably doing this too, so part of the calling convention states that EBP must be preserved by any C function. Hence the callee, if it is going to set up EBP as a frame pointer, must push the previous value first.
    The callee may then access its parameters relative to EBP. The doubleword at [EBP] holds the previous value of EBP as it was pushed; the next doubleword, at [EBP+4], holds the return address, pushed implicitly by CALL. The parameters start after that, at [EBP+8]. The leftmost parameter of the function, since it was pushed last, is accessible at this offset from EBP; the others follow, at successively greater offsets. Thus, in a function such as printf which takes a variable number of parameters, the pushing of the parameters in reverse order means that the function knows where to find its first parameter, which tells it the number and type of the remaining ones.
    The callee may also wish to decrease ESP further, so as to allocate space on the stack for local variables, which will then be accessible at negative offsets from EBP.
    The callee, if it wishes to return a value to the caller, should leave the value in AL, AX or EAX depending on the size of the value. Floating-point results are typically returned in ST0.
    Once the callee has finished processing, it restores ESP from EBP if it had allocated local stack space, then pops the previous value of EBP, and returns via RET (equivalently, RETN).
    When the caller regains control from the callee, the function parameters are still on the stack, so it typically adds an immediate constant to ESP to remove them (instead of executing a number of slow POP instructions). Thus, if a function is accidentally called with the wrong number of parameters due to a prototype mismatch, the stack will still be returned to a sensible state since the caller, which knows how many parameters it pushed, does the removing.
    There is an alternative calling convention used by Win32 programs for Windows API calls, and also for functions called by the Windows API such as window procedures: they follow what Microsoft calls the __stdcall convention. This is slightly closer to the Pascal convention, in that the callee clears the stack by passing a parameter to the RET instruction. However, the parameters are still pushed in right-to-left order.

    Thus, you would define a function in C style in the following way:


    global _myfunc

    _myfunc:
    push ebp
    mov ebp,esp
    sub esp,0x40 ; 64 bytes of local stack space
    mov ebx,[ebp+8] ; first parameter to function

    ; some more code

    leave ; mov esp,ebp / pop ebp
    ret

    At the other end of the process, to call a C function from your assembly code, you would do something like this:


    extern _printf

    ; and then, further down...

    push dword [myint] ; one of my integer variables
    push dword mystring ; pointer into my data segment
    call _printf
    add esp,byte 8 ; `byte' saves space

    ; then those data items...

    segment _DATA

    myint dd 1234
    mystring db 'This number -> %d <- should be 1234',10,0

    This piece of code is the assembly equivalent of the C code


    int myint = 1234;
    printf("This number -> %d <- should be 1234\n", myint);
    Baaaaaaaaah

  6. #6
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Some more about the __stdcall convention.


    In __stdcall, the parameters are pushed from left to right. So if you have this function:
    void __cdecl func1(int i1, int i2, int i3);
    you'd push the params like this:
    push [i3]
    push [i2]
    push [i1]
    but for this function
    void __stdcall func2(int i1, int i2, int i3);
    you'd do
    push [i1]
    push [i2]
    push [i3]

    The second difference is in who is responsible for clearing up. In __cdecl, where there may be a variable number of args it MUST be the caller who clears up. In __stdcall it is the called function. Since the order on the stack is
    ret address
    arg3
    arg2
    arg1
    the function cannot simply use esp arithmetics or pop instructions: the return address is in the way. Therefore a special version of ret is used:
    ret n
    where n is the number of bytes to clear. This instruction gets the return address, increases esp by n+4 and then transfers control to the return address.
    This implies that the number of bytes passed to such a function is constant, which is the reason for the third difference, the name mangling. A _cdecl function is simply mangled by adding a leading underscore
    func -> _func
    To assure that the caller of a __stdcall function pushes only the right number of bytes this number is included in the name
    func -> _func@n
    where n is the number of bytes this function will clear from the stack.
    e.g.
    void __stdcall func1(long, short, double);
    -> _func@14
    void __stdcall func2(char, void*);
    -> _func@4 or _func@6 (depending on 16 or 32 bit, near or far)
    Note that since the minimum push size is 2 bytes a char argument also takes 2 bytes.
    Maybe all arguments are multiples of 4 bytes on 32-bit systems, I'm not sure (I think the stdarg macros assume this, but that may apply only for the __cdecl convention).
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  7. #7

    Thread Starter
    Frenzied Member markman's Avatar
    Join Date
    Nov 2000
    Location
    Florida.
    Posts
    1,197
    thanks everyone
    retired member. Thanks for everything

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width