Click here to Skip to main content
15,886,518 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello. I am trying to convert this assembly code that I found on Github into inline assembly in C++. I have already added the asm function to the code, but the code breaks and won't compile. I am using Microsoft Visual C++ compiler to do this. This is a personal project so the code is only for my learning experience. I greatly appreciate any help.

Here is the code:

C++
#include <iostream>
#include <cmath>
#include <stdio.h>

using namespace std;
const int ARRAYSIZE = 30;

int main()
{
    int arr[ARRAYSIZE];
    int temp_arr[ARRAYSIZE];
    int number;

    for(int x = 0; x < ARRAYSIZE; x++)
    {
        number = (rand() % 99) + 1;
        arr[x] = number;
    }
    /*
     READ_ARR_LEN:
     __asm
     {
     // Read the length of the array
     //GetLInt [30]      // Size of input array
     //PutLInt [30]
     }

     GET_ARRAY:
     __asm
     {
     //intel_syntax
     // Get values in arr from the user
     mov   EAX, arr
     mov   ECX, ARR_LEN
     call  Read_Arr

     // Run Merge Sort on the array
     mov   EAX, arr
     mov   EBX, temp_arr
     mov   ECX, ARR_LEN
     call  Merge_Sort

     // EXIT
     }//
     */
Merge_Sort:
    __asm
    {
        // EAX - Array start
        // ECX - array length

        // Arrays of size 0 or 1 are already sorted
        cmp   ECX, 2
        jl    Trivial_Merge_Sort

        // Merge_Sort (first half)
        // Length of the first half
        // ECX /= 2
        push  ECX
        shr   ECX, 1
        call  Merge_Sort
        pop   ECX

        // Merge_Sort (second half)
        push  EAX
        push  EBX
        push  ECX

        // Length of the second half
        // ECX = ECX - ECX/2
        mov   EDX, ECX
        shr   EDX, 1
        sub   ECX, EDX
        imul  EDX, 4
        // Start index of the second half
        // EAX = EAX + (ECX/2) * 4
        add   EAX, EDX
        push  EDX
        call  Merge_Sort
        pop   EDX

        pop   ECX
        pop   EBX
        pop   EAX

        pushad
        // Merge (first half, second half)
        // Length of first half = ECX/2
        // Length of second half = ECX - ECX/2
        mov   EDX, ECX
        shr   ECX, 1
        sub   EDX, ECX

        // Start of second half = EAX + (ECX/2) * 4
        mov   EBX, EAX
        mov   EDI, ECX
        imul  EDI, 4
        add   EBX, EDI
        // Index of temp array = 0
        sub   EDI, EDI
        call  Merge
        popad

        // Copy back the merged array from temp_arr to arr
        call  Merge_Copy_Back_Temp

        ret
    };

Trivial_Merge_Sort:
    __asm
    {
        // In case of arrays of length 0 or 1
        ret
    };
Merge:
    __asm
    {
        // Merge two arrays contents.
        // The final merged array will be in temp_arr
        // Merging is done recursively.

        // Arguments:
        // EAX - First array's start
        // EBX - Second array's start
        // ECX - Length of first array
        // EDX - Length of second array
        // EDI - Index in temp array
        pushad

        // Handle the cases where one array is empty
        cmp   ECX, 0
        jz    First_Array_Over
        cmp   EDX, 0
        jz    Second_Array_Over

        // Compare first elements of both the arrays
        push  EDX
        push  EDI
        mov   EDX, [EAX]
        mov   EDI, [EBX]
        cmp   EDX, EDI
        pop   EDI
        pop   EDX

        // Pick which ever is the least and update that array
        jl    Update_First_Array
        jmp   Update_Second_Array
    };

Update_First_Array:
    __asm
    {
        // min_elem = min (first elements of first array and second array)
        // Put min_elem into the temp array
        push  dword ptr [EAX]
        pop   dword ptr [temp_arr + EDI * 4]
        add   EAX, 4
        dec   ECX
        inc   EDI

        // Recursively call Merge on the updated array and the
        // other array
        call  Merge
        popad
        ret
    };

Update_Second_Array:
    __asm
    {
        // min_elem = min (first elements of first array and second array)
        // Put min_elem into the temp array
        push  dword ptr [EBX]
        pop   dword ptr [temp_arr + EDI * 4]
        add   EBX, 4
        dec   EDX
        inc   EDI

        // Recursively call Merge on the updated array and the
        // other array
        call  Merge
        popad
        ret
    };

Merge_Copy_Back_Temp:
    __asm
    {
        // Copy back the temp array into original array
        // Arguments:
        // EAX - original array address
        // ECX - original array length
        pushad

        // For copying back, the destination array is EAX
        mov   EBX, EAX
        // Now, the source array is temp_arr
        mov   EAX, temp_arr
        call  Copy_Array
        popad
        ret
    };

Trivial_Merge:
    __asm
    {
        // Note: One array is empty means no need to merge.
        popad
        ret
    };

First_Array_Over:
    __asm
    {
        // Copy the rest of the second array to the temp arr
        // because the first array is empty
        pushad
        mov   EAX, EBX
        mov   ECX, EDX
        mov   EBX, temp_arr
        imul  EDI, 4
        add   EBX, EDI
        call  Copy_Array
        popad
        popad
        ret
    };

Second_Array_Over:
    __asm
    {
        // Copy the rest of the first array to the temp arr
        // because the second array is empty
        pushad
        mov   EBX, temp_arr
        imul  EDI, 4
        add   EBX, EDI
        call  Copy_Array
        popad
        popad
        ret
    };
Copy_Array:
    __asm
    {
        // Copy array to destination array
        // EAX - Array start
        // EBX - Destination array
        // ECX - Array length

        // Trivial case
        cmp   ECX, 0
        jz    Copy_Empty_Array

        push  ECX
        sub   EDI, EDI
    };
copy_loop:
    __asm
    {
        // Copy each element
        push  dword ptr [EAX + EDI * 4]
        pop   dword ptr [EBX + EDI * 4]
        inc   EDI
        loop  copy_loop

        pop   ECX
        ret
    };

Copy_Empty_Array:
    __asm
    {
        ret
    };

Read_Arr:
    __asm
    {
        // EAX - array start
        // ECX - array length
        mov   ESI, EAX
        sub   EDI, EDI
    };
loop1:
    __asm
    {
        // Read each element
        lea eax,[esi+edx*4]
        inc   EDI
        loop  loop1
        ret
    };

    return 0;
}
Posted

1 solution

Hi
your code compiles fine on my win7/x64/vs2010 system, but it crashes and I think this is because you are using indirections on registers which aren't loaded with proper addresses.

I brought the example to life by initializing with
ASM
Init:
     __asm
     {
     //instead of mov   EAX, arr
     lea   EAX, arr
     //instead of mov   EBX, temp_arr
     lea   EBX, temp_arr
     mov   ECX, ARRAYSIZE
     call  Merge_Sort
     jmp   finish
     }; 

right after the initial for loop which fills the array with random numbers,


then replacing all occurences of
ASM
mov <reg>, <c-array-name></c-array-name></reg>
with
ASM
lea <reg>, <c-array-name></c-array-name></reg>


and finally adding a
ASM
finish:

label right before
C#
    return 0;
}
 
Share this answer
 
Comments
merano 2-Feb-13 5:10am    
Works perfect if only replace lea for adresses, not for e.g. ARRAYSIZE

<asm>
GET_ARRAY:
__asm {
// Get values in arr from the user
// Run Merge Sort on the array
lea EAX, arr //instead of mov EAX, arr
lea EBX, temp_arr //instead of mov EBX, temp_arr
mov ECX, ARRAYSIZE //ARRAYSIZE (no lea!)
call Merge_Sort
jmp finish
}
<asm>

You get 5 from me!
saephoed 2-Feb-13 6:14am    
Merans, you wont Need the address of the Constantin ARRAYSIZE. Lea returns the effective address as a "Pointer" which doesn't make much Sense for a c Constant in this Example. When I tested it yesterday, the solution worked. Have to go now, but will post the full src maybe later.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900