CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Nov 2006
    Posts
    3

    Returning information from Assembly to C++ without registers

    I am in my first semester of assembly on the intel 86x processor, basicly I have been working on this problem for about two weeks and my book and net references haven't been able to help me out.

    I am doing a call from C++ into Assembly from this code.

    Code:
    enum ResultCode        {ShowSquare, ShowMultiply, ShowDivide, ShowRemainder, ShowDivideFailure};
    enum SuccessCode    {Failure, Success};
    
    extern "C" SuccessCode Divide (long, long, long &, long &);
    extern "C" void PrintResult (ResultCode, long);
    
    ...some code...main....
    
    cout << "Enter mumber to divide into then number to divide by" << endl;
    cin >> Num1 >> Num2;
    if (Divide (Num1, Num2, Result, Remainder) == Success)
    cout << "Result is " << Result << " and remainder is " << Remainder << endl<<endl;
    else
    cout << "Attempted division by zero" << endl<<endl;
    
    ...
    
    void PrintResult (ResultCode PrintCode, long Value)
        {
        switch (PrintCode)
            {
            case ShowDivide:
                    cout << "Display of divide is " << Value << endl;
                    break;
            case ShowRemainder:
                    cout << "Display of remainder is " << Value << endl;
                    break;
            case ShowDivideFailure:
                    cout << "Display of Division by zero" << endl;
                    break;
    I have most of the Assembly code up and working but I can't figure out how to modify the result and remainded parameters being passed into the Assembly call after the result and such has been found in my .asm file.

    Here is a snippet of my Assembly code

    Code:
    ;_Divide    proc dividend:DWORD, divsor:DWORD, result:DWORD, remained:DWORD
    _Divide    proc
            push    ebp
            mov    ebp, esp
            
    ;        mov        eax, dividend
    ;        mov        eax, divsor
    ;        mov        eax, result
    ;        mov        eax, remained
    ;        jmp        L2        
            
            mov        ecx, [ebp + 12]    ; num1 dividend
            mov        eax, [ebp + 8]    ; num2 divisor
    ;        cwd
    ;        mov        edx, eax
    ;        mov        eax, ecx
    ;        cwd
    ;        mov        edx, ebx
    ;        mov        ecx, eax
    ;        mov        eax, ebx
            
            cmp        ecx, 0
            jne        DividFunc
            push    0
            push    5
            call _PrintResult
            pop        eax
            pop        eax
            mov        eax, 0
            jmp        L2
    DividFunc:    
            sub        edx, edx
            idiv    ecx    ; product should be in eax
            cmp        edx, 0
            jne L1
            push    edx
            push    eax
            push    eax
            push    2
            call _PrintResult
            pop        eax
            pop        eax
            pop        eax
            pop        edx
            
    ;        mov    dword ptr [ebp+16], eax
    ;        mov dword ptr [ebp+20], edx
            
    ;        mov        ebx, dword ptr [ebp+16]
    ;        mov        ecx, dword  ptr [ebp+20]
    ;        mov        ebx, eax
    ;        mov        ecx, edx
            
            mov        eax, 1
            jmp L2
        L1:
            push    edx
            push    eax
            push    0
            push    3
            call _PrintResult
            pop        eax
            pop        eax
            pop        eax
            pop        edx
            mov eax, 1
        L2:
            pop    ebp
            ret
    _Divide endp

    My results when I run is;
    Code:
    Enter mumber to divide into then number to divide by
    250
    25
    Display of divide is 10
    Result is 200 and remainder is -858993460
    As you can see I've tried a number of different things since what logically I think should work hasn't...I would think that I should be able to reference the position [ebp+16] & [ebp+20] and do a mov into it. Any clarification would be greatly appreciated!

  2. #2
    Join Date
    Nov 2004
    Posts
    34

    Re: Returning information from Assembly to C++ without registers

    An important thing to remember is what kind of parameters are being passed on the stack. Are you passing by value or by reference?

    Also, you have fallen into a trap of referencing off of ebp. Remember you push ebp in your procedure to preserve it and just before that is your return address (pushed by the call instruction), so the very last parameter pushed onto the stack starts at [ebp+8]

    Another note: dividend should be in EAX, divisor in ECX.

    Here is a sample program in HLA, it should not be too hard to understand the workings, just remember in HLA, source and destination operands are reversed.

    Code:
    program divprog;
    
    	#includeonce ("stdlib.hhf")
    
    	?@nodisplay := true;
    	?@noalignstack := true;
    
    	procedure divide (	dividend:dword;	// passed by value
     						divisor:dword;	// passed by value
     						var res:dword;	// passed by reference
     						var remainder:dword);	// passed by reference
    		@noframe; 							
    	begin divide;
    		
    		push (ebp);
    		mov (esp, ebp);
    		mov ([ebp+20], eax); // dividend
    		mov ([ebp+16], ecx); // divisor
    		cmp (ecx, 0);
    		je done;
    		xor (edx, edx);
    		idiv (ecx);
    		
    		// save result into res
    		mov ([ebp+12], ecx); // address of result 
    		mov (eax, [ecx]);
    		mov ([ebp+8], ecx); // address of remainder
    		mov (edx, [ecx]);
    		
    	done:
    		pop (ebp);
    		ret (16);	// return balanced stack
    	end divide;
    
    	static
    		_res	:dword;
    		_rem	:dword;
    		
    
    begin divprog;
    
    	pushd (7);	// dividend
    	pushd (2);	// divisor
    	pushd (&_res);	// address of _res
    	pushd (&_rem);	// address of _rem
    	call divide;
    	stdout.put ("result:", _res, "  remainder:", _rem, nl);
    
    	// output from this program
    	//result:0000_0003  remainder:0000_0001
    
    end divprog;
    Of course, I don't recommend bouncing off EBP. It looks like you are using MASM, so you should be able to use the labels directly from a proc.
    Last edited by kahlinor; December 3rd, 2006 at 04:02 AM.

  3. #3
    Join Date
    Nov 2006
    Posts
    3

    Re: Returning information from Assembly to C++ without registers

    Thank you for the response, I actually managed to figure both of my posts out already but hadn't made it back here yet. Your examples and instructions were very easy to understand, Thank you.

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