[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17]
Define the fetch-execute cycle as it relates to a computer processing a program. Your definition should describe the primary purpose of each phase.
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.
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 R7, R4
ADD R4, R5, R4
MOV R5, R7
SUBS R6, R6, #1
BNE again
R4 |
7, | 11, | 18, | 29, | 47 |
R5 |
4, | 7, | 11, | 18, | 29 |
R6 |
4, | 3, | 2, | 1, | 0 |
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;
}
MOV R3, #1
MOV R1, #0
loop TST R0, R3
ADDNE R1, R1, #1
ADDS R3, R3, #1
BNE loop
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 R2, R2, #1
CMP R0, R1, LSL R2
BGT loop1
SUBLTS R2, R2, #1
BLT done
loop2 CMP R0, R1, LSL R2
SUBGE R0, R0, R1, LSL R2
SUBS R2, R2, #1
BGE loop2
done
(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 |
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 R0, R0, R1
SUB R1, R1, #1
CMP R0, #10 ; at addr 16
MOVGT PC, #28
MOV PC, #8
MOV R2, #1
halt B halt ; at addr 32
[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 |
For the below ARM assembly code, trace the values
as it executes that will be placed into the registers
R0, R1, and R2.
ADD R1, PC, #base ; puts 32 into R1
MOV R2, #0
loop LDR R0, [R1]
ADD R2, R2, R0
ADD R1, R1, R0
CMP R0, #0
BNE loop
halt B halt
base DCB 3, 4, 0, -2, 1, -3
R0 | 3 | −2 | 4 | −3 | 0 | |
R1 | 32 | 35 | 33 | 37 | 34 | 34 |
R2 | 0 | 3 | 1 | 5 | 2 | 2 |
For the below ARM assembly code, trace the values
as it executes that will be placed into the registers
R0, R1, and R2.
ADD R0, PC, #nums
loop LDRB R1, [R0], #1
SUBS R2, R1, #3
BLE loop
halt B halt
nums DCB 1, 2, 3, 4, 5
R0 |
20, | 21, | 22, | 23, | 24 |
R1 |
1, | 2, | 3, | 4 | |
R2 |
−2, | −1, | 0, | 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 R0, PC, #nums
MVN R1, #8 ; makes R1 be -9
loop LDRB R2, [R0], #1
ADDS R1, R1, R2
BLT loop
halt B halt
nums DCB 1, 2, 3, 4, 5
R0 |
24, | 25, | 26, | 27, | 28 |
R1 |
−9, | −8, | −6, | −3, | 1 |
R2 |
1, | 2, | 3, | 4 |
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.
SUB R2, R0, #4 ; R2 will be address of first zero found
again LDR R1, [R2, #4]!
CMP R1, #0
BNE again
SUB R0, R2, R0 ; now compute index corresponding to R2
MOV R0, R0, ASR #2 ; by subtracting R0 and dividing by 4
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.
MOV R2, R0 ; 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 R3, R0 ; Update R0 if this entry is larger
MOVGT R0, R3
start SUBS R1, R1, #1 ; Test whether any entries are left
BNE next
Explain the function of the link register (R14) on the ARM
processor.
When calling a subroutine, we place into the link register
the address of the instruction following the entry in the
subroutine.
This way, the subroutine code can determine the next
instruction to be executed after it is ready to return.
For example, if subroutine A decides that it wishes
to utilize subroutine B, then before A
jumps into B, it first places into R14 the address
of the next instruction to be executed after B completes.
Subroutine B will be written so that once it
completes, it looks into R14 to determine which
instruction to use next. In this way, B can be
written so that it will be able to work regardless of which
subroutine uses B.
Write an ARM assembly language instruction(s) to push
R4 onto the program stack referenced by SP.
Both STR R4, [SP, #-4]!
and STMDB SP!, { R4 } are good solutions.
Distinguish between callee-save registers (R4 through R11 in the ARM Procedure Call Standard) and caller-save registers (R0 through R3 in the ARM Procedure Call Standard).
If a subroutine uses callee-save registers, then it must ensure that their value upon returning is the same as their value when the subroutine begins. With caller-save registers, though, a subroutine is allowed to change them without restoring their initial values. (If the caller needs their values, it should save those registers' values itself.)
Using the ARM Procedure Call Standard, write a subroutine
max that takes two parameters a and b and
returns the larger of the two.
max CMP R0, R1
MOVLT R0, R1
MOV PC, LR
Suppose we have in another file written a subroutine labeled by
remain that given two parameters k and
n
returns the remainder when dividing n by k. This
subroutine uses the ARM Procedure Call Standard for parameter passing
and register usage.
Write an ARM program fragment that uses this remain
subroutine to add all the factors of R4 and place the
sum into R5. For example, if R4 holds 12
before your fragment is executed, then after it is executed
R5 should hold 16, since
1 + 2 + 3 + 4 + 6 = 16.
You may assume that R4 is at least 2.
MOV R5, #0
SUB R6, R4, #1
loop MOV R0, R4
MOV R1, R6
BL remain
TST R0, R0
BNE next
ADD R5, R5, #1
next SUBS R6, R6, #1
BNE loop
Complete the partial fragment below for setting the last value
of a linked list to 0,
where R4 is initially the address of the list's first node.
Each node holds its integer data in the first four bytes, and
in the next four bytes is the address of the node following it in the list.
The last node has 0
marked as the address of the following
node.
loop ; load address of node following R4 into R5; i.e., r5 = r4->next
TST R5, R5
MOVNE R4, R5
BNE loop
MOV R5, #0
; change value in node R4 to be R5; i.e., r4->value = r5
The short solution:
LDR R5, [R4, #4]
and then
STR R5, [R4].
The first instruction might be replaced by two lines:
ADD R0, R4, #4
LDR R5, [R0]
Suppose R4 holds the memory address of the first node
in a linked list of integers, where each node holds its integer
data in its first four bytes and the address of the node
following it in the next four bytes. The linked list is
terminated by an address of 0. Write an ARM assembly
fragment that places into R0 how many nodes the list contains.
Your fragment may change any other registers as it pleases.
MOV R0, #0
B start
next LDR R4, [R4, #4]
ADD R0, R0, #1
start CMP R4, #0
BNE next