CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9

Thread: Assembler

  1. #1
    Join Date
    May 2000
    Location
    Germany
    Posts
    369

    Assembler

    Hello!
    Can someone help me with the following assemblercode
    Code:
    extern "C" long double _cdecl exp (double x)
    _exp    PROC    NEAR
    PUBLIC  _exp
            FLDL2E
            FLD     QWORD PTR [ESP+4]             //; x
            FMUL                                  //; z = x*log2(e)
            FIST    DWORD PTR [ESP+4]             // round(z)
            SUB     ESP, 12
            MOV     DWORD PTR [ESP], 0
            MOV     DWORD PTR [ESP+4], 80000000H
            FISUB   DWORD PTR [ESP+16]            //; z - round(z)
            MOV     EAX, [ESP+16]
            ADD     EAX,3FFFH
            MOV     [ESP+8],EAX
            JLE     SHORT UNDERFLOW
            CMP     EAX,8000H
            JGE     SHORT OVERFLOW
            F2XM1
            FLD1
            FADD                                  //; 2^(z-round(z))
            FLD     TBYTE PTR [ESP]               //; 2^(round(z))
            ADD     ESP,12
            FMUL                                  //; 2^z = e^x
            RET
    
    UNDERFLOW: 
            FSTP    ST
            FLDZ                                  //; return 0
            ADD     ESP,12        
            RET
    
    OVERFLOW:
            PUSH    07F800000H                    //; +infinity
            FSTP    ST
            FLD     DWORD PTR [ESP]               //; return infinity
            ADD     ESP,16
            RET
    
    _exp    ENDP
    return 0
    }
    I want to use this function in my c++ programm. I am using Vc++ 6.0.

    Thanks in advance

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449
    It's not C++, so how do you propose to use it in a C++ program?

    Do you mean

    a) translate it into C++ code or

    b) place it in-line into the C++ code or

    c) use a seperate assembler and compile the code. Then include the obj in your project

    Which one a), b), or c), or do you have something else in mind?

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    May 2000
    Location
    Germany
    Posts
    369
    I want to use it inline in my code:

    If you are interested you can show me shortly how to solve my problem with each of your suggested solutions.

    Thanks
    Last edited by kakalake; May 6th, 2003 at 05:18 PM.

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449
    Originally posted by kakalake
    I want to use it inline in my code:

    If you are interested you can show me shortly how to solve my problem with each of your suggested solutions.

    Thanks
    You have to use the _asm keyword. It should be documented in the VC++ help.

    To translate it to C++, you have to know what the code is supposed to do and just rewrite it in C++.

    To compile it using a separate assembler, you have to get MASM or some other assembler to create an obj. Then you include the obj file in your project.

    Regards,

    Paul McKenzie

  5. #5
    Join Date
    May 2000
    Location
    Germany
    Posts
    369
    I already used the keyword _asm but it still doesn´t work.
    Code:
    double exp (double x)
    {
    	_asm 
    	{
    				FLDL2E
    				FLD     QWORD PTR [ESP+4]             //; x
    				FMUL                                  //; z = x*log2(e)
    				FIST    DWORD PTR [ESP+4]             // round(z)
    				SUB     ESP, 12
    				MOV     DWORD PTR [ESP], 0
    				MOV     DWORD PTR [ESP+4], 80000000H
    				FISUB   DWORD PTR [ESP+16]            //; z - round(z)
    				MOV     EAX, [ESP+16]
    				ADD     EAX,3FFFH
    				MOV     [ESP+8],EAX
    				JLE     SHORT UNDERFLOW
    				CMP     EAX,8000H
    				JGE     SHORT OVERFLOW
    				F2XM1
    				FLD1
    				FADD                                  //; 2^(z-round(z))
    				FLD     TBYTE PTR [ESP]               //; 2^(round(z))
    				ADD     ESP,12
    				FMUL                                  //; 2^z = e^x
    				RET
    
    		UNDERFLOW: 
    				FSTP    ST
    				FLDZ                                  //; return 0
    				ADD     ESP,12        
    				RET
    
    		OVERFLOW:
    				PUSH    07F800000H                    //; +infinity
    				FSTP    ST
    				FLD     DWORD PTR [ESP]               //; return infinity
    				ADD     ESP,16
    				RET
    
    	}
    
    	return 0;
    }
    Everything works fine but when the function jumps to the label Underflow, or Overflow it breaks with an access violation error. This error occurs when the label tries to RETurn with RET to the position where it was called.

  6. #6
    Join Date
    Apr 2003
    Posts
    1,755

    Smile

    You must not call RET in your directly in your code. This will invalidate the stack frame becuase when you entered the procedure, the compiler added this code to your own
    Code:
    push ebp
    mov  ebp, esp
    sub  esp, 40h
    push ...
    push...
    ...
    By calling RET in your code, you did not cleaned the ESP, so the return address is invalid.

    What you have to do is declare a double variable to store the result instead of directly accessing offsets of the esp and in your code, add a JUMPLABEL before the return statement and jump to that label instead of issuing RET.
    Code:
    double exp (double x)
    {
       double retval;
       __asm {
          
          ...
          ...
          JMP RETURN_RESULT
    
          UNDERFLOW: 
             ...
             ...
             JMP RETURN_RESULT
    
          OVERFLOW:
             ...
             ...
             JMP RETURN_RESULT
       }
    RETURN_RESULT:
       return retval;
    }
    Hope this will help you.

  7. #7
    Join Date
    May 2000
    Location
    Germany
    Posts
    369
    i have not written the code. I haven´t any experiences with assembler. Could you show me what you mean?

    Thanks

  8. #8
    Join Date
    Apr 2003
    Posts
    1,755

    Smile

    This is the modified code. I removed the ESP and replaced them with variable to avoid offset error.

    Code:
    double exp (double myval)
    {
       double retval = 0;
       DWORD tempval[3];
       __asm {
          FLDL2E
          FLD     QWORD PTR [myval]			//; x
          FMUL				//; z = x*log2(e)
          FIST    DWORD PTR [myval]			// round(z)
          MOV     DWORD PTR [tempval], 0
          MOV     DWORD PTR [tempval + 4], 80000000H
          FISUB   DWORD PTR [myval]			//; z - round(z)
          MOV     EAX, DWORD PTR [myval]
          ADD     EAX,3FFFH
          MOV     [tempval+8],EAX
          JLE     SHORT UNDERFLOW
          CMP     EAX,8000H
          JGE     SHORT OVERFLOW
          F2XM1
          FLD1
          FADD                                  //; 2^(z-round(z))
          FLD     TBYTE PTR [tempval]           //; 2^(round(z))
          FMUL                                  //; 2^z = e^x
          JMP     RETURN_RESULT
    
       UNDERFLOW: 
          FSTP    ST
          FLDZ                                  //; return 0
          JMP     RETURN_RESULT
    
       OVERFLOW:
          PUSH    07F800000H                    //; +infinity
          FSTP    ST
          ADD     ESP, 4
          FLD     DWORD PTR [tempval]           //; return infinity
    
       RETURN_RESULT:
          FST QWORD PTR [retval];
       }
       return retval;
    }
    Hope this will help you.
    Last edited by rxbagain; May 6th, 2003 at 08:57 PM.

  9. #9
    Join Date
    May 2000
    Location
    Germany
    Posts
    369
    Thanks a lot to all especially to rxbagain.

    Thanks, thanks, thanks ....

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured