Vous êtes sur la page 1sur 17

EECS 370 Midterm Exam

Winter 2017- Solutions


Notes:
Closed book. Closed notes.
?? problems on ?? pages. Count them to be sure you have them all.
Calculators without wireless are allowed, but no PDAs, Portables, Cell phones, etc.
ont spend too much time on any one problem.
This exam is fairly long: d
You have 90 minutes for the exam.
Some questions may be more difficult than others. You may want to skip around.
Show your work to receive partial credit.
Write legibly and dark enough for the scanners to read your work.

Write your uniqname on the line provided at the top of each page.

You are to abide by the University of Michigan/Engineering honor code. Please sign below to
signify that you have kept the honor code pledge:

I have neither given nor received aid on this exam, nor have I concealed any violations of the
Honor Code.

Signature: _________________________________________

Name: _________________________________________

Uniqname: _________________________________________

First and last name of person sitting to your right (write the symbol if at the end of a row):

_________________________________________

First and last name of person sitting to your left (write the symbol if at the end of a row):

_________________________________________
uniqname: ______________________

Do not write on this page.

Problem 1 _________ out of ??

Problem 2 _________ out of ??

Problem 3 _________ out of ??

Problem 4 _________ out of ??

Problem 5 _________ out of ??

Problem 6 _________ out of ??

Problem 7 _________ out of ??

Problem 8 _________ out of ??

Total: _________ out of ??


uniqname: ______________________

Problem 1. Short Questions Points: ___/ ??


Warmup Round

1) How many different memory locations can you access with an 8-bit memory address?

Answer: ______2^8 = 256_________

2) What does the terminal output when the following code is executed?

int a = 0b01001011;
a = (a >> 3) & 0x7;
printf(%d\n, a);

Answer: _________1_____________
Expressions that evaluate to 1 but are not 1 (ex. 0x1, 0b001) were not accepted.

3) The value 0x0EEC5370 is stored at memory addresses 100-103. What is the value
stored in r3 after this line of ARM assembly code executes, assuming little endian
format? (Assume r0 contains the value 0.)

ldrsb r3, [r0, #102]

Answer: ______0xFFFF FFEC______

4) Convert the number 2.25 to floating point. Write your answer in hex.

Answer: _______0x4010 0000_______

5) Which of the following is/are true of register files? Circle all that apply.

a) Accessing an element in a register file is faster than accessing an element in


memory.
b) The size of the register file is comparable to the size of memory.
c) Register files are located inside the CPU, unlike memory.

5)c) was not assigned any points during grading due to the ambiguity between memory
meaning main memory vs. cache memory. Had the question said main memory, c) should have
been circled.
uniqname: ______________________

For questions 6-10, circle whether the statement is True or False.

6) LC2K is a byte-addressable system.


True False

7) There is generally a 1-1 correspondence between assembly code and machine


language.
True False

8) For the same size of physical memory, a word-addressable system would have the
same number of distinct addresses as a byte-addressable system.
True False

9) Consider the following piece of code. Circle whether each variable goes on the stack,
heap, static, or text segment of memory. Assume function parameters are not loaded in
registers.

char *boo;
static int g = 1;
void foo(int* f) {
static char w = 2;
int y = 3;
void (*bar)(int*);
bar = &foo;
boo = (char*)malloc(4);
}

boo Stack / Heap / Static / Text

*boo Stack / Heap / Static / Text

g Stack / Heap / Static / Text

f Stack / Heap / Static / Text

w Stack / Heap / Static / Text

y Stack / Heap / Static / Text

bar Stack / Heap / Static / Text

*bar Stack / Heap / Static / Text


uniqname: ______________________

Problem 2: Data Alignment Points: ___ /??


Padding here, padding there, padding everywhere?

Assume a 32-bit architecture. alice begins at memory address 0x100.

struct Student;

struct Course {
struct Student* roster[700];
char* name;
};

struct Student { // Address Range:


int umid; // 1000 - 1003
double gpa; // 1008 - 1015
short num_courses; // 1016 - 1017
int num_credits; // 1020 - 1023
char permissions; // 1024 - 1024
struct Course* courses[6]; // 1028 - 1051
};

struct Student alice; // 1000 - 1055

lice
a) Fill in the blanks above to indicate the range of memory that each variable in a
occupies. Provide your answer in decimal.

b) Reorder the member variables in s truct Student to minimize the size, indicating each
members position by a number from 1 to 6 on the given lines.
Many possible solutions, but here are some:
struct Student {
2/3/4 3/4 int umid;
1 2 double gpa;
5 5 short num_courses;
2/3/4 3/4 int num_credits;
6 6 char permissions;
2/3/4 1 struct Course* courses[MAX_COURSES];
};
c) How many bytes of memory would a lice occupy using this new definition of s
truct
Student?
____48____ bytes
uniqname: ______________________

Problem 3: C to ARM Points: ___ /??


Forward to the past!

Convert the C function whoWon() to ARM assembly by filling in the blanks. Assume that all
registers are caller-saved, that function parameters are passed through registers r0 and r1, and
that the function returns a value through r0. All immediates should be expressed in
hexadecimal.

C Source Code

struct Contender {
char name[10];
short score1; // Scores can be negative
int scoreFinal;
};
int whoWon(struct Contender contenders[], int size){
int total = 0, maxScore = 0x80000000, maxScoreIndex = 0, i = 0;
for(i = 0; i < size; ++i){
total = contenders[i].score1 + contenders[i].scoreFinal;
if(total >= maxScore){
maxScore = total;
maxScoreIndex = i;
}
}
return maxScoreIndex;
}

ARM Assembly

mov r2, #0x0 // total = 0


mov r3, #0x80000000 // maxScore = 0x80000000
mov r4, #0x0 // maxScoreIndex = 0
mov r5, #0x0 // i = 0
loop: cmp r5, r1 // 1 point
bge end // 2 points
add r6, r0, r5 LSL #0x4 // 1point + 2 points
ldrsh r2, [r6, #0xA] // 2 points
ldr r7, [r6, # 0xC] // 1 point
add r2, r2, r7 // 1 point + 1 point
if: cmp r2, r3 // 1 point
movge r3, r2 // 2 points

movge r4, r5 // 1 point


add r5, r5, 0x1 // 2 points
b loop // 2 points
end: mov r0, r4 // set return value 1 point
uniqname: ______________________

bx r14 // return
uniqname: ______________________

Problem 4: ISA Addressing Modes Points: ___/??

Consider the following code:


1 mov r0, #0x1002
//r0 = 0x1002
2 mov r2, #2
//r2 = 0x02
3 ldrsh r1, [r0], #2
//r1 = M[1002] = 0x100C, r0=1004
4 ldrsh r2, [r0, r2, LSL, #1]
//r2 = 4, r2 = M[1004+4]=0xFFFF9FF7
5 and r3, r1, r2
//r3 = r1&r2 = 0x1004
6 str r2, [r3, #2]!
//r3 = 0x1006

1. For the code above, fill in the final state of the registers and memory. (Assume big-endian)

Regist Initial Final Value Memory Initial Value Final Value


er Value Address

r0 0x0 0x1004 0x1000 0x87A6100C 0x87A6100C

r1 0x0 0x100C 0x1004 0x2123A789 0X2123FFFF

r2 0x0 0xFFFF9FF7 0x1008 0x9FF75432 0X9FF75432

r3 0x0 0x1006 0x100C 0x23A82690 0X23A82690

2. What is the value in r1 after the execution of line 3?


a) 0x87A6 b) 0xFFF87A6 c) 0x100C d) 0xFFFF100C

3. What is the value in r3 after the execution of line 5?


a) 0x1000 b) 0x1002 c) 0x1004 d) 0x1008
uniqname: ______________________

Problem 5: LC2K Linear Search Points: ___/??

In this question, you will explore writing a simple LC2K assembly program to search an array of
integers.

Take a minute to get familiar with this snippet of C code:

int LC2K_linear_search (int[], int, int);

int main()
{
int arr[7];
LC2K_linear_search(arr, 7, 53);

return 0;
}

// arr is an array of size integers


// returns the index of the first occurrence of num in arr
// returns -1 if num is not found in arr
int LC2K_linear_search (int arr[], int size, int num)
{
int i;
for (i = 0; i < size; ++i)
if (arr[i] == num)
break;

if (i == size)
return -1;

return i;
}

A few things to note:


The C function parameters arr, size, num correspond to the LC2K labels a
rr,
size, num , respectively
Remember that r0 should always contain the value 0
The return value of LC2K_linear_search is stored in r7
uniqname: ______________________

a) Here is the above call to LC2K_linear_search after it has been compiled into LC2K
assembly code. Fill in the blanks to complete the implementation.

lw 0 1 one
add 0 0 2
lw 0 3 size
lw 0 4 num
lw 0 5 loop
jalr 5 6
end halt
loop beq 2 3 done
lw 2 5 arr
beq 5 4 done
add 1 2 2
beq 0 0 loop
done beq 2 3 error
add 0 2 7
beq 0 0 return
error lw 0 7 neg1
return jalr 6 5
one .fill 1
neg1 .fill -1
num .fill 53
size .fill 7
arr .fill 54
.fill 8
.fill 43
.fill 0
.fill 20
.fill 33
.fill 37
.fill 53
.fill 30

C2K_linear_search ? __7____
b) How many times does the for loop execute in this call to L

c) What is the return value of this call to LC2K_linear_search ? _____-1______


uniqname: ______________________

Problem 6: Caller/Callee Points: ___/15

Consider the following functions:

void foo(void) {

int r1 = 0, r2 = 0, r3 = 0;
int r4 = 5;

printf("This is a print statement\n");

r2 = r1 + r3 + r4;

bar();

for(; r2 != 0; r2--) {

printf("This is a while loop");

}
r4 = r3;

bar();
}

void bar(void) {

int r5 = 0, r6 = 0;
for(; r5 < 5; r5++) {

printf("This is a for loop\n");

}
uniqname: ______________________

Consider the C code on the previous page. Assume all variables are mapped to registers of the
same name. Only consider the loads and stores executed within the functions f oo() and bar().

Assume the only analysis the compiler can perform is liveness analysis.

A. First consider the case where all the registers are c aller saved, how many load/store
instruction pairs would be executed by the program if foo is called once? Then consider the
case where all registers are callee saved, how many load/store instruction pairs would be
executed by the program if foo is called once? Fill in the number of loads/stores in the table
below.
// 1 point per register, 12 total points for this part
Register # of Caller Load/Store Pairs Executed # of Callee Load/Store Pairs Executed

r1 1 1

r2 6 1

r3 7 1

r4 1 1

r5 10 2

r6 0 2

// 2 points for the correct answer, dependent on the answer for part A
b) What is the total number of load/store instructions executed when each of the variables are
optimally assigned to either caller or callee registers?

# of Load/Store Pairs Executed: ______6______


uniqname: ______________________

Problem 7: Object Files Points: ___/??


Objectively the best question.

Note: the #include <stdlib.h> at the top of osify.c allows that file to call functions malloc and free
defined elsewhere. Assume that every access to globals or values pointed to by globals must go
to memory.

main.c osify.c
int eecs370 = 370; 0: #include <stdlib.h>
extern double* eecs470; 1:
extern void no_time(); 2: double* eecs470;
extern void happier_days(); 3:
int level_up(); 4: void no_time(){
5: eecs470 = (double*) malloc(8);
int main() { 6: }
no_time(); 7:
eecs370 += 100; 8: void happier_days(double num) {
*eecs470 = (double) levelup(); 9: double eecs482 = num + 12;
happier_days(*eecs470); 10: free(eecs470);
return 0; 11: }
} 12:
13:
int level_up(){ 14:
return eecs370; 15:
} 16:
17:
18:

Fill out each object files data section. If a value isnt initialized, write N/A.
main.o Data Section osify.o Data Section
Name Initialized Value Name Initialized Value
eecs370 370 eecs470 N/A
uniqname: ______________________

For the following symbol tables, put the name of the symbol, and mark the type as T, D or U
depending on whether that symbol is in the Text or Data section or Undefined. If the symbol is
defined, put at which line it is defined in the c source file. Leave it blank otherwise.

main.o Symbol Table osify.o Symbol table


Name Type Line Name Type Line
(T/D/U) Number (T/D/U) Number
eecs370 D 0 eecs470 D 2
main T 6 no_time T 4
no_time U N/A malloc U N/A
eecs470 U N/A happier_days T 8
happier_days U N/A free U N/A
level_up T 14

Fill out each object files relocation table, with a line number that needs to be fixed up, the
instruction type (bl, str, or ldr), and the symbol that instruction is dependent on.

main.o Relocation Table osify.o Relocation Table


Line # Instr Type Dependency Line # Instr Type Dependency
( bl / str / ldr ) ( bl / str / ldr )
7 bl no_time 5 bl malloc
8 ldr eecs370 5 str eecs470
8 str eecs370 10 bl free
9 bl level_up 10 ldr eecs470
9 ldr eecs470
10 bl happier_day
s
10 ldr eecs470
15 ldr eecs370
uniqname: ______________________

Problem 8: LC2K CISC Edition Points: ___/28

After listening to feedback from loyal customers, Team EECS370 decided to upgrade LC2K to a
byte-addressable CISC architecture that supports up to 16 registers. Additionally, some of the
opcodes have been changed. The changes are summarized as follows:

Due to the CISC upgrade, instructions now have variable lengths (ie. 16-bit or 32-bit).
Due to byte-addressability, the PC is now incremented by 2 or 4 at the end of every
instruction based on the type of next instruction
beq branches to address PC + 4 + 2*offset, and jalr stores P C + 2 to regB.
lw has been replaced with m ov, which sets regA equal to an 8-bit signed offset
sw has been replaced with s wp, which swaps the content of [regB] with the value stored
at memory address M[[regA] + offset]. In a sense, this is a combined lw and sw.

All unspecified opcodes remain the same. However, instructions are now encoded differently
(due to the variable instruction lengths), as shown below. Note that unused bits are coded as 0.

R-Type (add 000 / nor 001):


Bits 15 14-12 11-8 7-4 3-0

Purpose unused Opcode regA regB regDest

M-Type (mov 010):


Bits 15 14-12 11-8 7-0

Purpose (unused) Opcode regA offsetField

I-Type (swp 011 / beq 100):


Bits 31 30-28 27-24 23-20 19-16 15-0

Purpose (unused) Opcode regA regB (unused) offsetField

J-Type (jalr 101):


Bits 15 14-12 11-8 7-4 3-0

Purpose (unused) Opcode regA regB (unused)

O-Type (halt 110 / noop 111):


Bits 15 14-12 11-0

Purpose (unused) Opcode (unused)

Use this information to answer the questions on the next page.


uniqname: ______________________

You may also use this table as a quick reference for CISC LC-2K (changes are highlighted):

Opcode Bits Type Description

add 000 R-Type Store regA + regB to regDest

nor 001 R-Type Store regA NOR regB to regDest

mov 010 M-Type Store 8-bit offset to regDest

swp 011 I-Type Swap the value of regB with the value in MEM[ regA + 16-bit offset
]

beq 100 I-Type If regA equal to regB, branch to PC + 4 + 2 * (16-bit offset)

jalr 101 J-Type Store (PC+2) into regB, then jump to regA.

halt 110 O-Type Stop the machine.

noop 111 O-Type Do nothing.

a) Convert the following code snippet into machine code using CISC LC-2K. Assume file starts
xpress your answers in hexadecimal.
from address 0, and .fill still uses 32-bit integers. E

bloop mov 13 -1 // 0x2DFF (2D81 ?)

swp 0 6 label1 // 0x3060000A

beq 6 13 bloop // 0x46D0FFFB (46D08005 ?)

label1 .fill 100 // 0x00000064

b) How much memory does the above machine code occupy in bytes (including the .fill)?

14 bytes

c) How can the processor tell if a machine-code instruction is 16 bits or 32 bits long? (Express
your answer in one sentence.)

Accept any answer that has the word Opcode in it.


uniqname: ______________________

d) Below is an incomplete CISC LC-2K assembly program that shuffles the position of 50
integers. The integers start at memory address 100. The program iterates through each
position, and swaps it with another random position, determined by the output of a function
called RNG. The function RNG takes in no inputs, and returns an integer between 1 and 50
through reg3. Assume all registers are initialized to 0.

Complete this CISC LC-2K code by filling in the blanks. Assume that RNG does not touch any
other registers, so you dont need to caller/callee save anything.

mov 2 50

swp 0 6 rngAdr # load r eg6 with addr of RNG

loop beq 1 2 end

add 1 1 5

add 5 5 5 # reg5 = 4 * i

swp 5 4 100 # grab ith int from memory

jalr 6 7 # returns a random int via reg3

add 3 3 3

add 3 3 3 # reg3 *= 4

swp 3 4 100 # swap ith int with RNGth int

swp 5 4 100 # place RNGth int at position

mov 5 1 # set reg5 = 1

add 1 5 1 # increment i

beq 0 0 loop

end halt

rngAdr .fill RNG