Review A: Introducing ARM assembly language: Questions

A1.1.

Define the fetch-execute cycle as it relates to a computer processing a program. Your definition should describe the primary purpose of each phase.

A2.1.

For the below ARM assembly code, trace the values as it executes that will be placed into the registers R4, R5, and R6.

       MOV R4#7
       MOV R5#4
       MOV R6#4
again  MOV R7R4
       ADD R4R5R4
       MOV R5R7
       SUBS R6R6#1
       BNE again
A2.2.

Translate the below C code for counting the 1 bits in R0 into ARM assembly code, using the registers indicated by the variable names.

r3 = 1;
r1 = 0;
while (r3 != 0) {
    if ((r0 & r3) != 0) {
        r1 = r1 + 1;
    }
    r3 = r3 + r3;
}
A2.3.

Suppose R0 contains an integer value a, and R1 contains an integer value b that is more than 0. Write an ARM assembly language fragment that leaves in R2 the value of ab — that is, R0 raised to the positive power found in R1. You may change the values in R0 and R1, but the value for R2 should be computed reflecting the initial R0 and R1 values.

A2.4.

Translate the below C fragment into an equivalent ARM assembly language program, using registers corresponding to the variable names. (As it happens, this code has the effect of placing into r2 the product of r0 and r1's initial values.)

r2 = 0;
while (r1 != 0) {
    if ((r1 & 1) != 0) {
        r2 += r0;
    }
    r0 <<= 1;
    r1 >>= 1;
}
while (1); // halting loop
A2.5.

For the below ARM assembly code, trace the values as it executes that will be placed into the registers R0, R1, and R2.

       MOV    R0#48
       MOV    R1#5
       MVN    R2#0   ; MVN, not MOV
loop1  ADD    R2R2#1
       CMP    R0R1, LSL R2
       BGT    loop1
       SUBLTS R2R2#1
       BLT    done
loop2  CMP    R0R1, LSL R2
       SUBGE  R0R0R1, LSL R2
       SUBS   R2R2#1
       BGE    loop2
done
A2.6.

For the below ARM assembly code, trace the values as it executes that will be placed into the registers PC, R0, R1, and R2.

       MOV R0#0     ; at addr 0
       MOV R1#5
       ADD R0R0R1
       SUB R1R1#1
       CMP R0#10    ; at addr 16
       MOVGT PC#28
       MOV PC#8
       MOV R2#1
halt   B halt         ; at addr 32
A2.7.

Explain what an ARM processor accomplishes in terms of accessing and changing its registers when it executes a BEQ instruction.

A3.1.

For the below ARM assembly code, trace the values as it executes that will be placed into the registers R0, R1, and R2.

       ADD R1PC#base   ; puts 32 into R1
       MOV R2#0
loop   LDR R0, [R1]
       ADD R2R2R0
       ADD R1R1R0
       CMP R0#0
       BNE loop
halt   B halt
base   DCB 340-21-3
A3.2.

For the below ARM assembly code, trace the values as it executes that will be placed into the registers R1, R2, and R3. Note that the first line places the number 32 into R0.

     ADD R0PC#nums ; places the address of nums[0] == 1 into R0
     MOV R1#0
loop ADD R2R0R1, LSL #2
     LDR R3, [R2]
     ADD R1R1R3
     CMP R1#10
     BLT loop
done B done
nums DCD 1123581321345589
A3.3.

For the below ARM assembly code, trace the values as it executes that will be placed into the registers R0, R1, and R2.

       ADD R0PC#nums
loop   LDRB R1, [R0], #1
       SUBS R2R1#3
       BLE loop
halt   B halt
nums   DCB 12345
A3.4.

For the below ARM assembly code, trace the values as it executes that will be placed into the registers R0, R1, and R2.

       ADD R0PC#nums
       MVN R1#8    ; makes R1 be -9
loop   LDRB R2, [R0], #1
       ADDS R1R1R2
       BLT loop
halt   B halt
nums   DCB 12345
A3.5.

Suppose R0 holds the address of the first entry in an array of four-byte integers. Write an ARM assembly language program fragment that places into R0 the index of the first 0 in that array. (You may assume that there is a 0 in the array.) For example, if the array is <9,7,8,0,6>, and R0 holds the memory address of the 9, your fragment will place 3 into R0, since the 0 is in slot 3 of the array.

A3.6.

Suppose R0 holds the address of the first entry in an array of four-byte integers, and R1 hold the number of entries in that array. Write an ARM assembly fragment that places into R0 the largest value of the array. You may change any other registers, and you may assume that the array contains at least one value.

A3.7.

Translate the below C code into ARM assembly code, using the registers indicated by the variable names. The C code presumes that r0 holds the address of the first entry of an array of integer values, and r1 indicates how many elements the array holds; the code removes all adjacent duplicates from the array.

r3 = 1;
for (r2 = 1r2 < r1r2++) {
    if (r0[r2] != r0[r2 - 1]) {
         r0[r3] = r0[r2];
         r3 += 1;
    }
}
r1 = r3;
A3.8.

Suppose we have defined the following C struct, which our C compiler has decided to compile with name being in the first four bytes and grade in the next four bytes.

struct student {
    char *name;
    int grade;
};

Now suppose R0 holds the address of an array of twenty 32-bit pointers to struct students; that is, each R0[i] holds an address where a struct student can be found in memory. Complete the below ARM assembly language fragment as indicated; following completion of the full fragment, R1 should become the sum of all grades in the course.

        MOV R1#0                 ; R2 will hold total of all grades seen
        MOV R2#0                 ; R2 is index where we are in array
again                              ; load R0[R2]->grade into R3



        ADD R1R1R3             ; total += loaded grade
        ADD R2R2#1             ; R2 += 1
        CMP R2#20                ; if R2 < 20, repeat
        BLT again
A3.9.

Suppose we represent a linked list in memory where each node is eight bytes long, with the node's integer data stored in the first four bytes and the address of the following node found in the following four bytes. The list's last node is marked by having 0 as the address of its following node.

Assuming that R0 initially holds the address of the list's first node, write an ARM assembly language fragment that counts how many nodes in a linked list have a negative number, placing the number found into R1.

Review A: Introducing ARM assembly language: Solutions

A1.1.

The fetch-execute cycle is the process by which a classical computer executes instructions. In the fetch phase, the computer determines which instruction to do next, by fetching that instruction from memory based on the current value of the program counter register. In the execute phase, the computer executes this instruction. The computer alternates between these two phases as long as it is on.

A2.1.
R4 7,11,18,29,47
R5 4, 7,11,18,29
R6 4, 3, 2, 1, 0
A2.2.
       MOV R3#1
       MOV R1#0
loop   TST R0R3
       ADDNE R1R1#1
       ADDS R3R3R3
       BNE loop
A2.3.
        MOV R2#1
loop    MUL R2R2R0
        SUBS R1R1#1
        BNE loop
A2.4.
      MOV R2#0
      CMP R1#0
      BEQ halt
loop: TST R1#1
      ADDNE R2R2R0
      MOV R0R0, LSL #1
      MOVS R1R1, ASR #1
      BNE loop
halt: B halt
A2.5.

(By the way, this fragment computes R0 % R1.)

R0 48, 8, 3
R1 5
R2 −1,0,1,2,3,4,3,2,1,0,−1
A2.6.

[Technically, PC would always be 4 more than listed below. However, the below answer is more intuitive and is acceptable, as long as you're consistent.]

PC: 0, 4, 8,12,16,20,24, 8,12,16,20,24, 8,12,16,20,28,32
R0: 0, 5, 9, 12
R1: 5, 4, 3, 2
R2: 1
A2.7.

It looks at the Z flag to see whether the Z flag is 0 or 1. If the Z flag is 0, then it changes R15 (the program counter) to the address named within the instruction. If the Z flag is 1, then it increases R15 by 4 (so that the next instruction executed is the next instruction after the BEQ instruction).

A3.1.
R0 3−2 4−3 0
R1323533373434
R2 0 3 1 5 2 2
A3.2.
R10 1 2 4 9 64
R2 32 36 40 48 68
R3 1 1 2 5 55
A3.3.
R0 20,21,22,23,24
R1 1, 2, 3, 4
R2 −2,−1, 0, 1
A3.4.
R0 24,25,26,27,28
R1 −9,−8,−6,−3, 1
R2 1, 2, 3, 4
A3.5.
       SUB R2R0#4     ; R2 will be address of first zero found
again  LDR R1, [R2#4]!
       CMP R1#0
       BNE again
       SUB R0R2R0      ; now compute index corresponding to R2
       MOV R0R0, ASR #2  ; by subtracting R0 and dividing by 4
A3.6.
       MOV R2R0          ; R2 is address of next entry to read
       LDR R0, [R2], #4    ; Initialize return value with first entry
       B start
next   LDR R3, [R2], #4    ; Retrieve next entry
       CMP R3R0          ; Update R0 if this entry is larger
       MOVGT R0R3
start  SUBS R1R1#1     ; Test whether any entries are left
       BNE next
A3.7.
        MOV R3#1
        MOV R2#1
loop    CMP R2R1
        BLT done
        LDR R4, [R0R2, LSL #2]
        SUB R5R2#1
        LDR R5, [R0R5, LSL, #2]
        CMP R4R5
        STRNE R4, [R0R3, LSL #2]
        ADDNE R3R3#1
        ADD R2R2#1
        B loop
done    MOV R1R3
A3.8.
LDR R3, [R0R2, LSL #2]
LDR R3, [R3#4]
A3.9.
     MOV R1#0        # no negative numbers found so far
loop TST R0R0        # see if R0 is NULL
     BEQ done
     LDR R2, [R0]      # load R0->data into R2
     CMP R2#0
     ADDLT R1R1#1  # increment R1 if R2 < 0
     LDR R0, [R0#4]  # load R0->next into R0, and repeat
     B loop
done