Search code examples
arrayscvisual-studioassemblyx86

how to sum two array elements in assembly?


(assembly code using visual studio syntax) I know it's an obvious question but I'm new to assembly.

I'm having problems to understand how does esi register work in an exercise like this:

#include <stdio.h>

int main()
{
    int a = 0;
    int b[5] = { 1, 2, 3, 4, 5 };
    int *c;

    c = &b[0];

    __asm {
        mov ebx, c 
        mov eax, dword ptr [ebx]
        mov esi, 3
        add eax, dword ptr [ebx+esi*4]
        mov ecx, eax
        mov a, ecx 
    }

    printf("sum of first and fourth element is: %d", a);
}

I need to print sum of first and fourth element. The program works as follows:

  • define a and the array b, define pointer c, and it points to the first element of b.
  • move c in ebx. [c points to the first element, and therefore ebx contains the first element]
  • move the things to which pointer points to into eax register. [it's ebx]
  • move 3 into esi register. [critical part I didn't understand]
  • add operator [critical part I didn't understand]
  • move operators [easy part, no problems]

my questions are:

  • why do I have to copy 3 into esi register?
  • why do I have to do this operations? [ebx+esi*4]

I know esi makes things a lot easier, but I don't understand how to use this register.


Solution

  • Adding the first and fourth elements of array b is written:

    int a = b[0] + b[3];
    

    Since pointer c is initialized to point to the first element of b, this is equivalent to

    int a = c[0] + c[3];
    

    To add c[3] with ebx containing the value of c, the code sets esi to 3 and uses add eax, dword ptr [ebx+esi*4]. This instruction adds a 32-bit value read from the memory int the array pointed to by ebx at index esi, multiplied by the size of int directly as part of the addressing mode.

    This would be useful and efficient if esi contained the result of some computation or the value of an argument, but for a constant index, a simpler way is to compute the offset at compile time:

    add eax, dword ptr [ebx+12]
    

    Also note that using ecx to store the result is redundant too.

    Here is a simplified version:

    #include <stdio.h>
    
    int main() {
        int a;
        int b[5] = { 1, 2, 3, 4, 5 };
        int *c = b;
    
        __asm {
            mov ebx, c
            mov eax, dword ptr [ebx]
            add eax, dword ptr [ebx+12]
            mov a, eax
        }
    
        printf("sum of first and fourth element is: %d\n", a);
        return 0;
    }
    

    Note however that it is unclear whether the assembly code can have side effects on ebx and esi without consequences...