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?
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
Related
i have a special case where i need to push arguments onto the stack one at a time and then call a function which takes a callable as an argument and pass those arguments that were pushed to the stack to the callable/function. to solve this i created a few functions in assembly to push arguments onto the stack and call a function passing those arguments. however it seams to work but my code started breaking in weird places whenever i made calls to other functions inside the callable passed to CallFunction.
i need this function to take any callable. any help would be much appreciated.
please note that std::bind and other similar functions are not an option. each argument needs to be pushed onto the stack one at a time using a function call and i need to be able to call functions between calls to PushArg and CallFunction should return the return value of the function it executes.
What ive tried:
saving the stack pointer at the beginning of the call and restoring it before i return (current state)
creating my own stack in memory for storing arguments (too complex and messy and not as efficient as just using the registers and existing stack. would like to avoid if possible)
Code:
.data
FunctionPointer QWORD 0
ReturnPointer QWORD 0
StackPointer QWORD 0
.code
ALIGN 16
FT_StartCall PROC
mov [StackPointer],rsp
ret
FT_StartCall ENDP
FT_PushIntPointer PROC
pop ReturnPointer
push rcx
push ReturnPointer
ret
FT_PushIntPointer ENDP
FT_CallFunction PROC
;save return address in Memory
pop ReturnPointer
mov FunctionPointer,rcx
pop rcx
pop rdx
pop r8
pop r9
push r9
push r8
push rdx
push rcx
call FunctionPointer
mov rcx,0
mov rdx,0
mov r8,0
mov r9,0
mov rsp, [StackPointer]
push ReturnPointer
ret
FT_CallFunction ENDP
END
C++:
extern "C" void* __fastcall FT_CallFunction(void* Function);
extern "C" void __fastcall FT_PushIntPointer(void* ArgOrPointer);
extern "C" void __fastcall FT_StartCall();
int ADD(int first,int second){
return first+second;
}
int main(){
FT_StartCall();
FT_PushIntPointer(3);
FT_PushIntPointer(2);
int res = FT_CallFunction(ADD);
return res;
}
Output:
5
As everyone agrees, you are delving into UB territory with this code, but it does have some experimental value, I guess.
You should consider allocating your own private stack for something a bit more robust.
This bit of code:
pop rcx
pop rdx
pop r8
pop r9
push r9
push r8
push rdx
push rcx
Does nothing, besides scrambling rcd, rdx, r8 and r9. You should remove it.
The same goes for this pîece of code:
mov rcx,0
mov rdx,0
mov r8,0
mov r9,0
Did you try something like this?
FT_CallFunction PROC
; save return address in Memory
pop [ReturnPointer]
; call and replace with our own return point.
call [rcx]
mov rsp,[StackPointer]
; return to caller
push [ReturnPointer]
ret
FT_CallFunction ENDP
I have tried to understand this basing on a square function in c++ at godbolt.org . Clearly, return, parameters and local variables use “rbp - alignment” for this function.
Could someone please explain how this is possible?
What then would rbp + alignment do in this case?
int square(int num){
int n = 5;// just to test how locals are treated with frame pointer
return num * num;
}
Compiler (x86-64 gcc 11.1)
Generated Assembly:
square(int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-20], edi. ;\\Both param and local var use rbp-*
mov DWORD PTR[rbp-4], 5. ;//
mov eax, DWORD PTR [rbp-20]
imul eax, eax
pop rbp
ret
This is one of those cases where it’s handy to distinguish between parameters and arguments. In short: arguments are the values given by the caller, while parameters are the variables holding them.
When square is called, the caller places the argument in the rdi register, in accordance with the standard x86-64 calling convention. square then allocates a local variable, the parameter, and places the argument in the parameter. This allows the parameter to be used like any other variable: be read, written into, having its address taken, and so on. Since in this case it’s the callee that allocated the memory for the parameter, it necessarily has to reside below the frame pointer.
With an ABI where arguments are passed on the stack, the callee would be able to reuse the stack slot containing the argument as the parameter. This is exactly what happens on x86-32 (pass -m32 to see yourself):
square(int): # #square(int)
push ebp
mov ebp, esp
push eax
mov eax, dword ptr [ebp + 8]
mov dword ptr [ebp - 4], 5
mov eax, dword ptr [ebp + 8]
imul eax, dword ptr [ebp + 8]
add esp, 4
pop ebp
ret
Of course, if you enabled optimisations, the compiler would not bother with allocating a parameter on the stack in the callee; it would just use the value in the register directly:
square(int): # #square(int)
mov eax, edi
imul eax, edi
ret
GCC allows "leaf" functions, those that don't call other functions, to not bother creating a stack frame. The free stack is fair game to do so as these fns wish.
So, I have a task that I need to convert from string for example string "542215" to int 542215 or with any other ASCII symbols. I am kindof new to assembly programming so, I have almost no clue to what I am doing with it, but I wrote my experimental code.
int main(int argc, char** argv)
{
int Letters;
char* argv1 = argv[1];
if (argc < 2) {
printf("Nepateiktas parametras*/\n");
return(0);
}
__asm {
push eax
push ebx
push ecx
xor ecx, ecx
mov eax, argv1
NextChar:
movzx eax, byte ptr [esi + ecx]
test eax, eax
jz Done
push ecx
sub eax, 48
push eax
call PrintIt
pop ecx
inc ecx
jmp NextChar
Done:
pop ecx
pop ebx
pop eax
PrintIt:
mov[Letters], eax
pop ecx
pop ebx
pop eax
};
printf("Count of letters in string %s is %d\n", argv[1], Letters);
return(0);
}
and I am getting error that "Run-time check failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
This error basicly gives me 0 ideas what is going on, or what even ESP is, so any help would be appreciated with my code.
you don't need to push/pop registers around your whole asm statement; MSVC already notices which registers you modify.
You're popping the registers twice at the end, when execution falls through from Done: to PrintIt. Or even worse, on strings of non-zero length, you're leaving the asm statement via a path of execution that does 3 pushes at the start, push ecx, push eax, call PrintInt, and then 3 pops. So one of your register-restores is actually reloading the return address pushed by call, and leaving 3 pushed values on the stack.
If you don't know that ESP is the stack pointer, one of x86's 8 general-purpose integer registers, you need to continue reading an intro to basic x86 asm before using stack instructions like push and call.
Also something about the fact that labels aren't the same thing as functions, and how execution continues to the next instruction.
And BTW, int->string will involve a multiply by 10. See NASM Assembly convert input to integer? for the standard algorithm and an asm implementation.
so I've been debugging this and made a function to send a packet to the server
here is the function
Naked void CB::Send_To_Server(CHARARRAY Buffer, int Length)
{
__asm
{
PUSH ESI
LEA EAX, Length
MOVZX ECX, DWORD PTR DS : [Buffer]
PUSH ECX
PUSH EAX
MOV ECX, NetworkClass
CALL Send_Packet_Original_Address
POP ESI
RET
}
}
the problem here is first when I debug my application it shows that
the function has 3 arguments instead of 2 (Buffer,Length,Length) and
when I use it it actually pushes the length twice the first time is the
correct length the second time it's some weird negative long number like
-29470056 <---- Not rly a value that showed to me just an example
so as you might see I am rly bad with both c++ and asm so if anyone has an
idea on how to fix this or maybe it's normal I'd rly appreciate your help :)
In order to refer to arguments by name EBP must be set to the value of ESP on entry to the function, if the function is not declared as naked this is done automatically.
I'm studying assembly language from the book "Assembly Language Step-by-Step: Programming with Linux" by Jeff Dunteman, and have come across an interesting paragraph in the book which I'm most likely misunderstanding, hence would appreciate some clarification on:
"The stack must be clean before we destroy the stack frame and return control. This simply means that any temporary values that we may have pushed onto the stack during the program’s run must be gone. All that is left on the stack should be the caller’s EBP, EBX, ESI, and EDI values.
...
Once the stack is clean, to destroy the stack frame we must first pop the caller’s register values back into their registers, ensuring that the pops are in the correct order.
...
We restore the caller’s ESP by moving the value from EBP into ESP, and finally pop the caller’s EBP value off the stack."
Consider the following code generated from Visual Studio 2008:
int myFuncSum( int a, int b)
{
001B1020 push ebp
001B1021 mov ebp,esp
001B1023 push ecx <------------------
int c;
c = a + b;
001B1024 mov eax,dword ptr [ebp+8]
001B1027 add eax,dword ptr [ebp+0Ch]
001B102A mov dword ptr [ebp-4],eax
return c;
001B102D mov eax,dword ptr [ebp-4]
}
001B1030 mov esp,ebp
001B1032 pop ebp
001B1033 ret
The value of ecx (indicated), pushed to make space on the stack for my variable c, is, as far as I can see, only gone from the stack when we reset ESP; however, as quoted, the book states that the stack must be clean before we reset ESP. Can someone please clarify whether or not I am missing something?
The example from Visual Studio 2008 doesn't contradict the book. The book is covering the most elaborate case of a call. See the x86-32 Calling Convention as a cross-reference which spells it out with pictures.
In your example, there were no caller registers saved on the stack, so there are no pop instructions to be performed. This is part of the "clean up" that must occur before mov esp, ebp that the book is referring to. So more specifically, let's suppose the callee is saving si and di for the caller, then the prelude and postlude for the function might look like this:
push ebp ; save base pointer
mov ebp, esp ; setup stack frame in base pointer
sub esp, 4 ; reserve 4 bytes of local data
push si ; save caller's registers
push di
; do some stuff, reference 32-bit local variable -4(%ebp), etc
; Use si and di for our own purposes...
; clean up
pop di ; do the stack clean up
pop si ; restoring the caller's values
mov esp, ebp ; restore the stack pointer
pop ebp
ret
In your simple example, there were no saved caller registers, so no final pop instructions needed at the end.
Perhaps because it's simpler or faster, the compiler elected to do the following instruction in place of sub esp, 4:
push ecx
But the effect is the same: reserve 4 bytes for a local variable.
Notice the instruction:
push ebp
mov ebp,esp ; <<<<=== saves the stack base pointer
and the instruction:
mov esp,ebp ; <<<<<== restore the stack base pointer
pop ebp
So after this sequence the stack is clean again