Assembly and C example

main() driver program

// demonstrate the random() function
// 2019-12-05
#include <stdio.h>
#include <stdlib.h> // random()
#include <time.h>   // time()

#define ARYSIZE 10

int minimum(int *array, int length);

int main(int argc, char **argv)
{
    srandom( time(NULL) );

    // First generate some random data:
    int data[ARYSIZE];
    for (int i = 0; i < ARYSIZE; i++) {
        data[i] = (random());
        printf("data[%2d] : %10d\n", i, data[i]);
    }

    // Try out the minimum() function:
    int min = minimum(data, ARYSIZE);
    printf("minimum  : %10d\n", min);

    return 0;
}

minimum() in C

// accept an integer array and a length,
// find the minimum value of array, and return it.
int minimum(int *array, int length)
{
    int i = 0;
    int min;
    min = *(array+i);   // a.k.a. array[i]
    for (i = 1; i < length; i++) {
        if (*(array+i) < min)   // or, "if (array[i] < min)"
            min = *(array+i);   //          "min = array[i];"
    }
    return min;
}

minimum() in assembly

The starting point:

// minimum: find the smallest integer in an array
// expects:
//      x0: array address
//      x1: array length
// returns:
//      smallest integer in x0
    .text
    .global minimum
minimum:
    stp fp, lr, [sp, -0x20] !   // leave space for i and min, as well
    mov  fp, sp                 // establish new frame pointer

minimum() in assembly

The finished function:

// minimum: find the smallest integer in an array
// expects:
//      x0: array address
//      x1: array length
// returns:
//      smallest integer in x0
    .text
    .global minimum
minimum:
    stp fp, lr, [sp, -0x20] !   // leave space for i and min, as well
    mov  fp, sp                 // establish new frame pointer

    mov  w2, 0                  // int i = 0;
    ldr  w3, [x0, x2, lsl 2]    // min = *(array + i);
    str  w3, [fp, 0x10]         // copy min into stack frame

    mov  w2, 1                  // initial condition
loop_test:
    cmp  w2, w1                 //  i < length?
    b.ge loop_end

    ldr  w4, [x0, x2, lsl 2]    // *(array+i)
    ldr  w5, [fp, 0x10]         // retrieve current min value
    cmp w4, w5
    b.ge loop_next
    str  w4, [fp, 0x10]         // min = *(array+i);
loop_next:
    add w2, w2, 1               //  i++;
    b    loop_test

loop_end:
    ldr  w0, [fp, 0x10]         // min is return value
    ldp  fp, lr, [sp], 0x20    // post-increment clears the stack frame
    ret
//--------

assembly minimum(), optimized

The minimum() assembly function, with an optimized loop and only using registers:

// minimum: find the smallest integer in an array
// expects:
//      x0: array address
//      w1: array length
// returns:
//      smallest integer in w0
    .text
    .global minimum
minimum:
    stp fp, lr, [sp, -0x10] !   // leave space for i and min, as well
    mov  fp, sp                 // establish new frame pointer

    mov  w2, 0                  // int i = 0;
    ldr  w3, [x0, x2, lsl 2]    // min = *(array + i);
    b    loop_next
loop:
    ldr  w4, [x0, x2, lsl 2]    // *(array+i)
    cmp  w4, w3
    b.ge loop_next
    mov  w3, w4                 // min = *(array+i);
loop_next:
    add w2, w2, 1               //  i++;
    cmp  w2, w1                 //  i < length?
    b.lt loop

loop_end:
    mov  w0, w3                 // min is return value
    ldp  fp, lr, [sp], 0x10     // post-increment clears the stack frame
    ret
//--------