News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Inline Assembly Code Help

Started by magus841, May 09, 2010, 06:00:35 PM

Previous topic - Next topic

magus841

Hello again! I'm trying to use inline assembly code in a C++ program and it kind of works. Here's the code:


#include <iostream>
using namespace std;

int addstuff(int x, int y);

int main(){
    int x = 2;
    int y = 3;
    int z = addstuff(x, y);

    cout << z << endl;

    return 0;
}

int addstuff(int x, int y){

    __asm{
   push ebp
   mov ebx, [ebp + 12]
   add ebx, [ebp + 8]
   mov eax, ebx
   pop ebp
   ret
    }
}



I'm using the debugger in Visual Studio and found out that the program blows up at the "ret" operand. I thought that my return value had to be in the eax register and also that ret would put me back up in main(). Not quite sure what to do here. Any help is appreciated as always :) Thank you.

Slugsnack

You're missing a mov ebp, esp and also you probably don't want to clobber ebx.

qWord

you also should notice that the compiler generates prologue and epilogue code. Use the naked attribute (VC++) for function declaration to skip this:
__declspec( naked ) int addstuff(int x, int y)
{...}
FPU in a trice: SmplMath
It's that simple!

Vortex

qWord is right. The solution is to use naked functions. A Pelles C example :


#define WIN32_LEAN_AND_MEAN
#include <windows.h>

__declspec(naked) char* UpperCase(char* szText) /* Turn off framing to get a smaller sized function */
{
__asm{
mov eax,[esp+4]
sub eax,1
__repeat:
add eax, 1
movzx ecx, BYTE PTR [eax]
cmp ecx, 0
je __end
cmp ecx,97 /* if ASCII(ecx) < 97 then ignore the charater */
jb __repeat
cmp ecx,122 /* if ASCII(ecx) > 122 then ignore the charater */
ja __repeat
sub BYTE PTR [eax], 32 /* convert lowecase to uppercase */
jmp __repeat
__end:
mov eax,[esp+4]
ret
}
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
char msg[]="inline assembly programming";
MessageBox(0,UpperCase(msg),"Hello!",MB_OK);
return 0;
}

magus841

Okay. That helps. It works.


__declspec(naked) int addstuff(int x, int y){
    __asm{
   push ebp
   mov ebp, esp
   mov eax, [ebp + 12]
   add eax, [ebp + 8]
   pop ebp
   ret
    }
}


One other question. Can I call MS-DOS interrupts in an __asm block? For example, if I wanted to change the function to type void and output my sum in the function, could I do that somehow with MS-DOS interrupts?

dedndave

DOS interrupts only work in 16-bit programs
if it is a 16-bit program, you should be able to use them inline

magus841

Okay. That's fine. My program isn't a 16-bit program. Would I be able to change my function to type void and output my sum somehow using the assembler code?

dedndave

welll - C normally uses the EAX register for a return value
alternatively, you may save it into some variable address
pass the address of a variable (i.e. a pointer) to the function - then let the function modify that variable
there are a few ways to go about it - but those are probably the 2 simplest and most common methods

Slugsnack

Yes pick the function you wish to use to output and call it with pushes and call. You could use printf, stdout, etc.

MichaelW

Quote from: magus841 on May 09, 2010, 06:56:29 PM
Would I be able to change my function to type void and output my sum somehow using the assembler code?

You could, but why do this? The speed advantage of inline assembly in a naked function would be lost if the code called some slow output function.

You could minimize your naked function to something like this:

__declspec( naked ) int addstuff_naked0( int x, int y )
{
    __asm
    {
      mov eax, [esp+4]
      add eax, [esp+8]
      ret
    }
}


eschew obfuscation

magus841

Quote from: MichaelW on May 09, 2010, 08:29:26 PM
Quote from: magus841 on May 09, 2010, 06:56:29 PM
Would I be able to change my function to type void and output my sum somehow using the assembler code?

You could, but why do this? The speed advantage of inline assembly in a naked function would be lost if the code called some slow output function.

You could minimize your naked function to something like this:

__declspec( naked ) int addstuff_naked0( int x, int y )
{
    __asm
    {
      mov eax, [esp+4]
      add eax, [esp+8]
      ret
    }
}




The way my assignment is written, I'm not allowed to change the code in main(). My professor wrote a function and has the output all happening down there. I'm only allowed to touch the code in the function.

MichaelW

To output from the assembly code you would basically push the parameters in right to left order as they appear in the target function's prototype, call the function using the correct name, and then, assuming that the called function uses the C calling convention, remove the parameters from the stack after the call returns (with an ADD ESP, N where N it the total number of parameter bytes).
eschew obfuscation