Inline assembly language - c++

I am doing 64 bit migration and i need to port inline assembly code to cpp Here is he code
void ExternalFunctionCall::callFunction(ArgType resultType, void* resultBuffer)
{
// I386
// just copy the args buffer to the stack (it's already layed out correctly)
int* begin = m_argsBegin;
int* ptr = m_argsEnd;
while (ptr > begin) {
int val = *(--ptr);
__asm push val
}
}
I want to migrate this __asm push val to cpp. This function is called four times and for every call we get different values of m_argsBegin and m_argsEnd(both m_argsBegin and m_argsEnd are dynamic arrays).
This while loop executes 4 times for every call of this "callFunction" function. So, in total 4x4 = 16 values are to be stored in a "CONTINUOUS memory location" this is what "__asm push val" does i guess. I need to implement this in c++ . I tried every possible way (stack, array, Lnked list, Queue even separated this into a separate asm file but none are working)
Can anyone help?
I separated this inline assembly function into a separate assembly file . Here is the code:
.386
.model c,flat
public callFunction_asm
CSEG segment public 'CODE'
callFunction_asm PROC
push ebp
mov ebp, esp
mov ecx, [ebp+8] ;val
push dword ptr [ecx]
mov esp, ebp
pop ebp
RETN
callFunction_asm ENDP
CSEG ends
END
where callFunction_asm is an extern function , I declared it as:
extern "C"
void callFunction_asm(int val);
and I am calling this function as:
while (ptr > begin) {
int val = *(--ptr);
callFunction_asm(val); //possible replacement
}
but even this is not working, can anyone tell where am I going wrong. I am new to assembly coding.

push puts its operand on the stack, as well as decrementing the stack pointer.
If you looked at the stack pointer plus 1 (1($sp)), you should see the value (but if you wanted it back, you'd typically use pop).

Related

Decoding assembly from MSVC 32-bit release (homework). What does no-op do?

Hi heads up this is a homework. I'm given an assembly generated by MSVC 32-bit Release with optimizations on, and I'm supposed to decode it back into C++. I've included the top of the function to the line I'm having problems with. The comments are mine, which I'm wrote while trying to understand this.
Note: Code is supposedly generated from C++. Not traditional ASM.
Note 2: There is one area of undefined behavior in the code.
Here are the lines I'm stuck with
TheFunction: ; TheFunction(int* a, int s);
0F2D4670 push ebp ; Push/clear/save ebp
0F2D4671 mov ebp,esp ; ebp now points to top of stack
0F2D4673 push ecx ; Push/clear/save ecx
0F2D4674 push ebx ; Push/clear/save ebs
0F2D4675 push esi ; Push/clear/save esi
0F2D4676 mov ebx,edx ; ebx = int s
0F2D4678 mov esi,1 ; esi = 1
0F2D467D push edi ; calling convention ; Push/clear/save edi
0F2D467E mov edi,dword ptr [a (0F2D95E8h)] ; edi = a[0]
0F2D4684 cmp ebx,esi ; if(s < 1)
0F2D4686 jl SomeFunction+3Ch (0F2D46ACh) ; Jump to return
0F2D4688 nop dword ptr [eax+eax] ; !! <-- No op involving dereferencing? What does this do?
0F2D4690 mov eax,dword ptr [edi+esi*4-4] ; !! <-- edi is *a, while esi is 1. There is no address
here!
..... More code but I've figured these out ....
I've more or less got the gist of the function. Its a function that takes a pointer to an int, with an underlying array, and a size. It then goes through each element in the array from last to first, adding to each subsequent one and printing it out. However, I still haven't got the details down and need help
Two questions, both at the end of the code snippet. What does no op on a dereference pointer do, and am I reading the last line in that its attempting to dereference something not in memory?
The nop dword ptr [eax+eax] instruciton does nothing. It doesn't even access the memory location given by the operand. It literally performs no operation.
It's just there so the next instruction is aligned to a 16-byte boundary. You'll notice that next instruction address is 0F2D4690 which ends with 0 which means it's 16-byte aligned. This can improve the performance of loops. Somewhere there will be an instruction that jumps back to 0F2D4690 as part of a loop. This particular form of a NOP instruction is used because it encodes a single NOP instruction in 8 bytes.
There is no corresponding C++ code for this instruction. You shouldn't try to represent it in your C++ code, just ignore it.
Also note that your comment for mov edi,dword ptr [a (0F2D95E8h)] is incorrect. Instead of being edi = a[0] it's simply edi = a. The variable a isn't a parameter at all, instead it's a global (or file level static) variable located at memory location 0F2D95E8h. This instruction just loads the value from memory.

My assembly function push data twice

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.

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?
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

Accessing function parameters in C++ from assembly in IA-32

I have been learning IA-32 assembly programming. So I would like to write a function in assembly and call it from C++.
The tutorial I am following is actually for x64 assembly. But I am working on IA-32. In x64, it says function arguments are stored in registers like RCX, RDX, R8, R9 etc.
But on searching a little bit, I could understand in IA-32, arguments are stored in stack, not in registers.
Below is my C++ code :
#include <iostream>
#include <conio.h>
using namespace std;
extern "C" int PassParam(int a,int b);
int main()
{
cout << "z is " << PassParam(15,13) << endl;
_getch();
return 0;
}
Below is assembly code for PassParam() function (it just add two arguments, that's all. It is only for learning purpose) :
PassParam() in assembly :
.model C,flat
.code
PassParam proc
mov eax,[ebp-212]
add eax,[ebp-216]
ret
PassParam endp
end
In my assembly code, you can see I moved first argument from [ebp-212] to eax. That value is obtained as follows :
I wrote PassParam() function in C++ itself and disassembled it. Then checked where ebp is and where is second argument stored (arguments are stored from right to left). I could see there is a difference of 212, so that is how i got that value. Then as usual, first argument is stored 4 bytes later. And it works fine.
Question :
Is this the correct method to access arguments from assembly ? I mean, is it always [ebp-212] where argument stored?
If not, can anyone explain the correct method to pass arguments from C++ to assembly ?
Note :
I am working with Visual C++ 2010, on Windows 7 machine.
On 32bit architectures, it depends on the calling convention, Windows for example has both __fastcall and __thiscall that use register and stack args, and __cdecl and __stdcall that use stack args but differ in who does the cleanup. MSDN has a nice listing here (or the more assembly orientated version). Note that FPU/SSE operations also have their own conventions.
For ease and simplicity, try use __stdcall for everything, this allows you to use stack frames to access args via MOV r32,[EBP+4+(arg_index * 4)], or if you aren't using stack frames, you can use MOV r32,[ESP+local_stack_offset+(arg_index * 4)]. The annotated C++ -> x86 Assembly example here should be of help.
So as a simple example, lets say we have the function MulAdd in assembly, with the C++ prototype int __stdcall MulAdd(int base, int mul, int add), it would look something like:
MOV EAX,[ESP+4] //get the first arg('base') off the stack
MOV ECX,[ESP+8] //get the second arg('mul') off the stack
IMUL EAX,ECX //base * mul
MOV ECX,[ESP+12] //get arg 3 off the stack
ADD EAX,ECX
RETN 12 //cleanup the 3 args and return
Or if you use a stack frame:
PUSH EBP
MOV EBP,ESP //save the stack
MOV EAX,[EBP+8] //get the first arg('base') off the stack
MOV ECX,[EBP+12] //get the second arg('mul') off the stack
IMUL EAX,ECX //base * mul
MOV ECX,[EBP+16] //get arg 3 off the stack
ADD EAX,ECX
MOV ESP,EBP //restore the stack
POP EBP
RETN //return to caller
Using the stack frame avoids needing to adjust for changes made to the stack by PUSH'ing of args, spilling or registers or stack allocations made for local variables. Its downside is that it reduces the number of registers you have to work with.

Defining a variable inside c++ inline assembly

Let's say we have the following c++ code:
int var1;
__asm {
mov var1, 2;
}
Now, what I'd like to know is if I didn't want to define var1 outside the __asm directive, what would I have to do to put it inside it. Is it even possible?
Thanks
To do that, you'll need to create a "naked" method with _declspec(naked) and to write yourself the prolog and the epilog that are normally created by the compiler.
The aim of a prolog is to:
set up EBP and ESP
reserve space on stack for local variables
save registers that should be modified in the body of the function
An epilog has to:
restore the saved register values
clean up the reserved space for local variables
Here is a standard prolog
push ebp ; Save ebp
mov ebp, esp ; Set stack frame pointer
sub esp, localbytes ; Allocate space for locals
push <registers> ; Save registers
and a standard epilog:
pop <registers> ; Restore registers
mov esp, ebp ; Restore stack pointer
pop ebp ; Restore ebp
ret ; Return from function
Your local variables will then begin at (ebp - 4) and go downward to (ebp - 4 - localbytes). The function parameters will start at (ebp + 8) and go upward.
It' impossible to create a C variable in assembler: the C compiler has to know about the variable (ie its type and address), which means it has to be declared in the C code.
What can be done is accessing symbols defined in assembler via extern declarations in C. That won't work for variables with automatic storage duration, though, as these don't have a fixed address but are referenced relative to the base pointer.
If you don't want to access the variables outside of the asm block, you can use the stack for storing assembler-local data. Just keep in mind that you have to restore the stack pointer to its previous value when leaving the asm block, eg
sub esp, 12 ; space for 3 asm-local 32bit vars
mov [esp-8], 42 ; set value of local var
[...]
push 0xdeadbeaf ; use stack
[...] ; !!! 42 resides now in [esp-12] !!!
add esp, 16 ; restore esp
If you don't want the relative addresses of the local variables to change whenever you manipulate the stack (ie use push or pop), you have to establish a stack frame (ie save the base of the stack in ebp and address locals relative to this value) as described in cedrou's answer.
Local variables are allocated and freed by manipulating the available space on the call stack via the ESP register, ie:
__asm
{
add esp, 4
mov [esp], 2;
...
sub esp, 4
}
Generally, this is better handled by establishing a "stack frame" for the calling function instead, and then access local variables (and function parameters) using offsets within the frame, instead of using the ESP register directly, ie:
__asm
{
push ebp
mov ebp, esp
add esp, 4
...
mov [ebp-4], 2;
...
mov esp, ebp
pop ebp
}