neo
neo

Reputation: 11

How does this line of ARM work?

I am having some trouble figuring how this assembly code works. I know it loops 16 times and updates the total every iteration. Specifically on the line at the .L2 label, wouldn't that give a segmentation fault since the previous line: ldr ip, [ip, #0] reassigns ip? Can someone explains how this works? Thank you in advance for your time.

.L5:
    .word data
    .word total
_start:
    ldr ip, .L5
    mov r1, #0
    ldr r0, .L5+4
    mov r3, r1
    mov r2, r1
    ldr ip, [ip, #0]
    str r1, [r0, #0]
.L2:
    ldr r1, [ip, r3]
    add r3, r3, #4
    cmp r3, #64
    add r2, r2, r1
    str r2, [r0, #0]
    bne .L2

Upvotes: 0

Views: 1444

Answers (1)

Iwillnotexist Idonotexist
Iwillnotexist Idonotexist

Reputation: 13457

Your code:

  • Loads the addresses of data in ip and the address of total in r0.
  • Zeroes registers r1, r2 and r3
  • Loads into ip the contents of data, replacing the previous contents (the address of data). This does not segfault. You are allowed to load from memory into any register, including the one you just used to specify the effective address for the load. All that happens is the usual: Whatever old value was there (in this case, the pointer) is replaced with the new value (the pointee).
  • Stores 0 into total.
  • Repeats 16 times:
    • Using ip as the base address of an array of integers, load into r1 the integer at offset r3 from the base address.
    • Accumulate r1 into the register r2.
    • Store r2 to total.

Based on this, I believe that data is of type int* and that total is of type int. Therefore, my interpretation of your assembler is:

Pseudocode-y C-like assembler

int* data;
int total;


void start(void){
    int** ip = &data;
    int*  r0 = &total;
    int r1=0, r2=r1, r3=r1;

    int* ipnew = *ip;
    *r0 = r1;/* total = 0; */

    do{
        r1 = *(int*)((char*)ipnew + r3);/* r1 = ipnew[r3/4]; */
        r3 += 4;
        r2 += r1;
        *r0 = r2;/* total = r2; */
    }while(r3 != 64);
}

Pure C

int* data;
int  total;

void start(void){
    int* arr = data;      /* ip */
    register int  sum = 0;/* r2 */
    register int  i   = 0;/* r3, divided by 4 */

    total = 0;

    do{
        sum   += arr[i++];/* r1 contains the value loaded from the array. */
        total  = sum;     /* r0 contains &total */
    }while(i != 16);
}

Upvotes: 1

Related Questions