Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use variables in __asm?

I'm compiling this C++ code with the VC compiler. I'm trying to call a function that takes two WORD (aka unsigned short) parameters using the __asm statement, like this:

__declspec(naked) void __stdcall CallFunction(WORD a, WORD b)
{
    __asm {
        PUSH EBP
        MOV EBP, ESP
        PUSH a
        PUSH b
        CALL functionAddress
        LEAVE
        RETN
    }
}

The function at functionAddress simply outputs the result of doing a + b. Then calling CallFuncion(5, 5); prints "64351" or something like that. The problem is when using the a and b variables inside the __asm statement because this works:

PUSH EBP
MOV EBP, ESP
PUSH 5
PUSH 5
CALL functionAddress
LEAVE

This is the function at functionAddress:

void __stdcall Add(WORD a, WORD b)
{
    WORD c;
    c = a + b;
    printf("The result is %d\n", c);
}

How can I do this the right way? So the __asm statement interpretate the a and b values?

like image 547
cdonts Avatar asked Oct 02 '22 20:10

cdonts


1 Answers

Since you're using __declspec(naked) and setting up your own stack frame, I don't believe the compiler will let you refer to a and b by name. Using __declspec(naked) basically means you're responsible for dealing with the stack frame, parameters, etc., on your own.

You probably want code more on this general order:

__asm {
    PUSH EBP
    MOV EBP, ESP 
    mov eax, [ebp+8]
    mov ebx, [ebp+12]
    push eax
    push ebx
    CALL functionAddress
    LEAVE
    RETN
}

I'ts been a while since I've handled things like this by hand, so you might want to re-check those offsets, but if I recall correctly, the return address should be at [ebp+4]. Parameters are (usually) pushed from right to left, so the the left-most parameter should be next at [ebp+8], and the next parameter at [ebp+12] (keeping in mind that the stack grows downward).

Edit: [I should have looked more carefully at the function heading.]

You've marked CallFunction as using the __stdcall calling convention. That means it's required to clean up the parameters that were passed to it. So, since it receives 8 bytes of parameters, it needs to remove 8 bytes from the stack as it returns:

    PUSH EBP
    MOV EBP, ESP
    mov eax, [ebp+8]
    mov ebx, [ebp+12]
    push eax
    push ebx
    CALL Add_f
    LEAVE
    RET 8
like image 105
Jerry Coffin Avatar answered Oct 05 '22 12:10

Jerry Coffin