English 中文(简体)
How do I pass arguments to C++ functions when I call them from inline assembly
原标题:

So, I would like to be able to call functions from a c++ dll. For certain reasons, I would like to call them from an __asm block in my C++ code. My question is this: I know that before I call the function, I have to push its arguments on the stack in the order specified by the function s calling convention.However, can i simply do something like this:

int a=5;   
double b = 5.0;  
__asm{  
       push b 
       push a  
       call functionAddress  
}

What worries me is the fact that I seem to remember that the standard word size in assembly is 2bytes, while the size of an int in C++ is usually 4bytes, and 8 bytes for a double.So , in the example above, am I really pushing the full value of each variable, or just the first couple of bytes? If the code above is not correct, what would be the right way to do it? Also, if the function we are calling returns a double, where is this value stored? I m assuming it can t be in a register, because it can only store 32bits ( 4bytes ).Any help with this mess would be greatly appreciated :)

最佳回答

To push 8-byte values such as doubles, you won t be able to use a regular PUSH instruction. And neither do you push floating-point parameters (or doubles) on to the floating-point stack. You need to put these fat parameters on the stack by hand . For example, to push π as a parameter to a function f:

  __asm {
    FLDPI                    // load pi onto FP stack
    SUB ESP,8                // make room for double on processor stack
    FSTP QWORD PTR [ESP]     // store pi in proc stack slot (and pop from FP stack)
    CALL f
    ADD ESP,8                // clean up stack (assuming f is _cdecl)
  }
问题回答

The 32-bit x86 architecture automatically pads values being pushed onto the stack to 32 bits.

There is something you have to keep in mind. If the function you re calling uses the __cdecl calling convention, you must "pop" what you pushed afterwards. However, for __stdcall functions you must not do this.

extern "C" int    __cdecl   function1(int, double);
extern "C" double __stdcall function2(char, char*);

int a = 5;
double b = 5.0;
int retval1;
char c =  5 ;
char *d = "Hello";
double retval2;

__asm {
    push b
    push a
    call function1
    add esp, 4*2 // "pop" what we pushed
    mov retval1, eax
    push d
    push c
    call function2
    mov retval2, eax
}

Generally, you would be pushing the full size of the computer word. This varies according to the chip, but on a 32 bit Intel would be 4bytes, and on a 64 bit Intel, would be 8 (depending on the compiler -- Visual Studio still only supports IA32 assembly -- so 4 bytes).

The best answer is to look at the documentation for your specific compiler.





相关问题
Call stack in compiled matlab

In matlab one can use dbstack to retrieve the call stack at the current time, however dbstack is not available in standalone compiled versions of matlab programs, is there an alternative to get the ...

Treating Warnings as Errors

I have a php application that I have just re-factored. Unfortunately it spewing out warnings like: Warning: preg_match() expects parameter 2 to be string, object given in /home/yacoby/dev/netbeans/...

Is there a call stack level limit?

I have a couple of colleagues looking at some bad code in Excel VBA, wondering is there a limit to the number of levels in a call stack

What does each entry in the Jmp_buf structure hold?

I am running Ubuntu 9.10 (Karmic Koala), and I took a look at the jmp_buf structure which is simply an array of 12 ints. When I use setjmp, and pass in a jmp_buf structure—4 out of 12 entries ...

热门标签