CPSC 323: Midterm 1
What can you do once GDB pauses a program's execution? (select all that apply, you may search online for answers)
Continue to the next line of the program Move back to the previous line of the program Print the values of variables Modify the control flow of your program Change the value of variables
The next questions refers to the object code (.o) generated after compilation but before linking of the following source code: // ... various includes etc ... int a[ 10 ] = {1,2,3,4,5,6,7,8,9,10}; long b = 0; int c[ 10 ]; static int d = 10; int main() { int e; int f = 3; // ... some code that uses all the variables ... return 0; } // Questions: Which variables(s) reside in the data section? Which variable(s) reside in the bss section? Which of the following symbols are not exported when this source code file is compiled to an object file?
a and d b and c d 1. a and d are global variables with a non-zero initialization 2. b and c are global variables with zero initialization 3. d is static so the symbol is not exported to other translation units; e&f are automatic variables
As an application of the property a ^ a = 0 (where ^ is the symbol for XOR) for any bit vector a, consider the following program - void inplace_swap(int *x, int *y) {*y = *x ^ *y; //step 1 *x = *x ^ *y; //step 2 *y = *x ^ *y; //step 3 } As the name implies, the effect of this procedure is to swap the values stored at the locations denoted by the pointer variables x and y. Note that unlike the usual technique for swapping two values, we do not need a third location to temporarily store one value while we are moving the other. Starting with values a and b in the locations pointed by x and y respectively, fill the table that follows, giving the values stored at the two locations after the end of each step of the procedure. Use the properties of XOR to show that the desired effect is achieved, and write the XOR operation using "^". Reduce the expression as much as possible at each step and do not use spaces.
a, a^b b, a^b b, a
The Valgrind error message "Invalid read" appears when a program attempts to access a region of memory that is not ____.
allocated
Consider a source file `source.c`, which can be compiled into the executable called `app` using the command `./compile`. Fill in the parts of a Makefile rule for this situation: (multiple fill-in-the-blank)
app: source.c ./compile
long bar(long arg1, long arg2, long arg3, long arg4, long arg5, long arg6) { // function definition} In the x86_64 assembly code for this function, where would the arguments be stored?
arg1 -> %rdi arg2 -> %rsi arg3 -> %rdx arg4 -> %rcx arg5 -> %r8 arg6 -> %r9
A line of code where GDB pauses a program's execution is called a
breakpoint
The list of function calls shown by GDB's `backtrace` command is called the ____ ____. (two words)
call stack
Given the following C code, fill in the blanks to create an equivalent IA32 assembly code. int max(int x, int y) { if (x > y) return x; else return y; } Assembly: movq %rsi, %rdx movq %rdi, %rax ____ %rax, %rdx ____ L9 movq %rdx, %rax L9: ret // QUESTIONS: What should go in the first blank? What should go in the second blank? How many memory references can happen at least? How many memory references can happen at most?
cmpl jle 8 9
A ____ graph is a type of directed graph used by `make` to accomplish incremental compilations.
dependency
GDB is able to locate logic errors in a program without any programmer involvement.
false
The ____ is the area of memory that is managed by the programmer with malloc and free.
heap
Convert two's complement 0xC521 to decimal notation.
-15,071
Suppose that you use 1 bit for the sign, 3 bits for the exponent, and 14 bits for the mantissa and that you represent numbers in normalized notation. Assume that setting exponent bits to all 0s or 1s are special cases. What is the smallest number that you can represent, assuming the same bias? Again, truncate the result to the third decimal place.
-15.999
Suppose that you have a 7-bit number represented in two's complement. What is the smallest value that you can represent (write in decimal, human notation)?
-64
Fast Inverse Square Root (Text) One of the nice (or bad) things that C allows is pointer casting from data type to another. Let's see an example of why one would even do this and why C allows you to have a powerful and efficient program perhaps at the cost of portability and programmability.Inverse square root (1/x) is one of the operations that is repeatedly performed in a lot of areas. For example, in signal analyses (e.g. for normalizing a vector) and graphics (e.g. angles of incidence for lighting). These examples also run this function for a large number of times. In the graphics example, an inverse square root operation may need to be performed anywhere between 1000 to 10000 times per 15 ms, which continues to rise with the increasing graphic quality demanded by recent games and movies. However, this operation is quite costly. x here is a floating-point number, and the operation needs a square root and a divide on a floating-point. To give you an idea, a floating-point divide takes roughly 25 cycles while a floating-point square root can take over 50 cycles.Note that multiplications and additions in floating-point are cheap compared to division taking roughly 2-5 cycles. Also, multiplications and divisions by powers of 2 are also extremely cheap, since it simply involves addition or subtraction of the exponent.Below is the code for approximating the inverse square root used in Quake 3 Arena, a game best known for its 3D graphics, with some light edits to the comments - 1 :float Q_rsqrt( float number ) 2 :{ 3 : int32_t i; 4 : float x2, y; 5 : const float threehalfs = 1.5F; 6 : 7 : x2 = number * 0.5F; 8 : y = number; 9 : i = * ( int32_t * ) &y; // evil floating point bit level hacking 10: i = 0x5f3759df - ( i >> 1 ); // what the hugs? 11: y = * ( float * ) &i; 12: y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration, newton's approximation 13: // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed 14: 15: return y; 16:} You should note that int32_t and float are both 32 bits wide here. The number 0x5f3759df is a constant here used as an approximation for sqrt(2^(127)). By simply counting the number of operations involved here, you can see that this approximation extremely fast, compared to doing the sqrt and the division. We won't go through why this works (but you should be able to reason about it with your knowledge of floating-point representation). If you would like to know more, you can search for "Fast inverse square root algorithm" or even simply "0x5f3759df" to get an explanation for it. However, let's try to solve a working example of the algorithm for number=0.15625. The inverse sqrt of 0.15625 is approximately 2.52982. Question: Fast Inverse Square Root Part 5 For the expression evaluated in part 3, if the bit pattern is evaluated as an IEEE 32-bit floating-point number, what is the value of the exponent in decimal form?
-65
Suppose you use a 4-bit binary encoding to represent the decimal value of 5. What is the value of the most significant bit (MSB)?
0
Fast Inverse Square Root (Text) One of the nice (or bad) things that C allows is pointer casting from data type to another. Let's see an example of why one would even do this and why C allows you to have a powerful and efficient program perhaps at the cost of portability and programmability.Inverse square root (1/x) is one of the operations that is repeatedly performed in a lot of areas. For example, in signal analyses (e.g. for normalizing a vector) and graphics (e.g. angles of incidence for lighting). These examples also run this function for a large number of times. In the graphics example, an inverse square root operation may need to be performed anywhere between 1000 to 10000 times per 15 ms, which continues to rise with the increasing graphic quality demanded by recent games and movies. However, this operation is quite costly. x here is a floating-point number, and the operation needs a square root and a divide on a floating-point. To give you an idea, a floating-point divide takes roughly 25 cycles while a floating-point square root can take over 50 cycles.Note that multiplications and additions in floating-point are cheap compared to division taking roughly 2-5 cycles. Also, multiplications and divisions by powers of 2 are also extremely cheap, since it simply involves addition or subtraction of the exponent.Below is the code for approximating the inverse square root used in Quake 3 Arena, a game best known for its 3D graphics, with some light edits to the comments - 1 :float Q_rsqrt( float number ) 2 :{ 3 : int32_t i; 4 : float x2, y; 5 : const float threehalfs = 1.5F; 6 : 7 : x2 = number * 0.5F; 8 : y = number; 9 : i = * ( int32_t * ) &y; // evil floating point bit level hacking 10: i = 0x5f3759df - ( i >> 1 ); // what the hugs? 11: y = * ( float * ) &i; 12: y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration, newton's approximation 13: // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed 14: 15: return y; 16:} You should note that int32_t and float are both 32 bits wide here. The number 0x5f3759df is a constant here used as an approximation for sqrt(2^(127)). By simply counting the number of operations involved here, you can see that this approximation extremely fast, compared to doing the sqrt and the division. We won't go through why this works (but you should be able to reason about it with your knowledge of floating-point representation). If you would like to know more, you can search for "Fast inverse square root algorithm" or even simply "0x5f3759df" to get an explanation for it. However, let's try to solve a working example of the algorithm for number=0.15625. The inverse sqrt of 0.15625 is approximately 2.52982. // QUESTION: Fast Inverse Square Root Part 2 For the variable in part 1, what is the value if you interpret this bit pattern as an IEEE 32-bit floating-point number?
0.1563
Suppose that you use 1 bit for the sign, 3 bits for the exponent, and 14 bits for the mantissa and that you represent numbers in normalized notation. Assume that setting exponent bits to all 0s or 1s are special cases. What is the smallest positive number (normalized) that you can represent, ignoring 0? Again, truncate the result to the third decimal place
0.25
Convert -512 (decimal) into hexadecimal with one's complement. Use 16 bits. Remember to format the answer with 0x.
0xFDFF
Convert -512 (decimal) into hexadecimal with two's complement. Use 16 bits. Remember to format the answer with 0x.
0xFE00
Given the following initial values and IA32 instructions, use these initial values for each question given below (each question is based on the initial values, not any changes the previous question might or might not implement). Address Value 0x100 0xFF 0x104. 0xAB 0x108. 0x13 0x10C 0x11 Register Value rax 0x100 rbx 0x104 rcx 0x001 rdx 0x003 ///QUESTIONS: movq 0x100, %rax #What is stored in rax? movq (%rax, %rdx, 4), %rcx #What is stored in rcx? dec %rcx #What is stored in rcx? leaq (0, %rbx, 5), %rcx #What is stored in rbx?
0xFF 0x11 0x00 0x104
#define NUMS (5) typedef struct abc { char* t; int** s; } abc; int main() { char* cities[] = {"New Haven", "New York City", "Boston"}; int vars[4] = {4, 5, 6, 7}; int nums[NUMS] = {1, 2, 3, 4, 5}; int* ptr[NUMS]; for (int i = 0; i < NUMS; i++) { ptr[i] = &nums[i]; } abc one; one.s = &(ptr[NUMS-3]); } // Calculate: nums[atoi(&cities[0][5])];
1
How many kilobytes do you need in order to represent the binary value corresponding to decimal number of 2^8191 + 2^5?
1
Suppose that you have a 7-bit number represented in two's complement. How many representations of 0 do you have with this? (Answer field is numerical)
1
Suppose you use a 4-bit binary encoding to represent the decimal value of 5. What is the value of the least significant bit (LSB)?
1
Fast Inverse Square Root (Text) One of the nice (or bad) things that C allows is pointer casting from data type to another. Let's see an example of why one would even do this and why C allows you to have a powerful and efficient program perhaps at the cost of portability and programmability.Inverse square root (1/x) is one of the operations that is repeatedly performed in a lot of areas. For example, in signal analyses (e.g. for normalizing a vector) and graphics (e.g. angles of incidence for lighting). These examples also run this function for a large number of times. In the graphics example, an inverse square root operation may need to be performed anywhere between 1000 to 10000 times per 15 ms, which continues to rise with the increasing graphic quality demanded by recent games and movies. However, this operation is quite costly. x here is a floating-point number, and the operation needs a square root and a divide on a floating-point. To give you an idea, a floating-point divide takes roughly 25 cycles while a floating-point square root can take over 50 cycles.Note that multiplications and additions in floating-point are cheap compared to division taking roughly 2-5 cycles. Also, multiplications and divisions by powers of 2 are also extremely cheap, since it simply involves addition or subtraction of the exponent.Below is the code for approximating the inverse square root used in Quake 3 Arena, a game best known for its 3D graphics, with some light edits to the comments - 1 :float Q_rsqrt( float number ) 2 :{ 3 : int32_t i; 4 : float x2, y; 5 : const float threehalfs = 1.5F; 6 : 7 : x2 = number * 0.5F; 8 : y = number; 9 : i = * ( int32_t * ) &y; // evil floating point bit level hacking 10: i = 0x5f3759df - ( i >> 1 ); // what the hugs? 11: y = * ( float * ) &i; 12: y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration, newton's approximation 13: // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed 14: 15: return y; 16:} You should note that int32_t and float are both 32 bits wide here. The number 0x5f3759df is a constant here used as an approximation for sqrt(2^(127)). By simply counting the number of operations involved here, you can see that this approximation extremely fast, compared to doing the sqrt and the division. We won't go through why this works (but you should be able to reason about it with your knowledge of floating-point representation). If you would like to know more, you can search for "Fast inverse square root algorithm" or even simply "0x5f3759df" to get an explanation for it. However, let's try to solve a working example of the algorithm for number=0.15625. The inverse sqrt of 0.15625 is approximately 2.52982. // QUESTION: Fast Inverse Square Root Part 4 For the expression evaluated in part 3, if the bit pattern is evaluated as an IEEE 32-bit floating-point number, what is the value of the mantissa in decimal form?
1.125
If 2^N bytes is a kilobyte, what is N?
10
// declarations int i, j, k[10] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; int *ip; char a, b, c[10] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; char *cp; void *vp; typedef struct stst {int i; char *p; } st; //assignment statements st x; ip = &k[4]; vp = ip; cp = &c[0]; x.p = cp + 3; x.i = 27; // Calculate: *(cp+1);
12
Suppose that you have a 4-bit binary number. We refer to the LSB as bit 0, and the MSB as bit 3 Now suppose that the LSB is 0 and the MSB is 1. Further, suppose that the overall impact of bits 1 and 2 is that they contribute an overall decimal value of 4. What is the overall decimal value of the number represented by this binary value?
12
Ignoring OVERFLOW, how many gate delays would a 4-bit ripple carry adder take if it can use only 2-input gates?
12, or 0
Moore's Law (Part 1) Moore's law is: A physical law of nature that states that the number of transistors in a chip doubles roughly every 18 month
False
True or False: A data type's alignment rules will be met in only the heap but not the stack.
False
True or False: If you get the compiler to create a file that stores the assembly equivalent of a C program in Intel's x86-64 ISA, it will have a mix of CISC and RISC instructions.
False
True or False: RISC instructions place the register sources in the same bit-locations, but the register destination can vary.
False
True or False: The bss region is usually fetched from secondary storage
False
True or False: The number of architecturally-exposed registers in the system equals the number of physical registers within the CPU.
False
Suppose that you have a 7-bit number represented in two's complement. Can you have overflow if you add one positive number with one negative number in this representation?
No
Constant propagation is not a peephole optimization because: 1. The optimization analysis spans a window of statements at a time. 2. False. It is infact, a peephole optimization. 3. The optimization analysis spans only the current statement at a time.
Only 1
What structure is used to convert architecturally-exposed register names in the CPU to physical register name within the hardware, without software involvement? Write down the answer as a three-letter acronym.
RAT
The `make` tool can: (select all that apply)
Run commands besides compilations Interpret variable definitions in Makefiles
void func(int * arr, int n){ if (arr == NULL) { arr = (int *) malloc(n * sizeof(int)); } for(int i =0 ; i < n ; i++){ arr[i] = i; } } int main() { int array[10]; int * array2 = NULL; func(array, 10); func(array2, 10); for(int i = 0 ; i < sizeof(array)/sizeof(array[0]); i ++) { printf("%d\n", array2[i] * array[i]); } } // Question: What is the output of this code?
Segmentation Fault
Dennard Scaling Dennard scaling states that: beyond transistor density, power is important -- i.e., that transistor density can increase within the same power budget.
True
Moore's Law (Part 2) Moore's law has led to: transistors today that are in the 3.5-14nm range
True
Moore's Law (Part 3) Moore's law is: An extrapolation of observed empirical data, rather than a physical law of nature
True
Moore's Law (Part 4) Moore's law is: A proxy for how processor performance has been increasing exponentially over the history of computing
True
This is not an example of constant folding. Before: int x = 5, y, z; // some code y = z * x; After: int x = 5, y, z; // some code y = z * 5;
True
True or False: A program's virtual address space is linear, contiguous, byte-addressable and maintains one segment for code & constant global variables, one segment for modifiable global variables, one segment for the heap, and one segment for the stack.
True
True or False: CISC instructions are more complex to decode.
True
True or False: CISC instructions reduce code footprint
True
True or False: RISC instructions are usually fixed-width.
True
True or False: The stack grows towards lower addresses.
True
True or False: x86-32 and x86-64 are examples of a CISC ISA.
True
int foo(int n){ int i,j; int x = 5; int y = 10; for (i = 0, i<n; i++) { for (j=0; j<n; j++) { if (i%2) { x += (4*j + 5*i); y += (7 + 4*j); } } } return (x * y); } // Questions: Analyze the above code w.r.t optimization opportunities and select the correct answer: None of the given options There is scope for constant propagation in this code. There is scope for constant folding in this code. There is scope for deadcode elimination in this code.
True False False False
The following questions refer to the following two source code files: foo.c: #include "stdio.h" int a; extern int b; static int c; int d; static int e; int sum(); int main() { a = 1; b = 2; c = 3; d = 4; e = 5; printf("Sum = %d\n",sum()); return 0; } bar.c: extern int a; extern int b; extern int c; static int d; static long int f = 1; int sum() { return (a+b+c+d+f); } Consider the object files produced by individually compiling each file when answering the following questions. Assume that the object file corresponding to foo.c is called foo.o, and assume that the object file corresponding to bar.c is called bar.o. Additionally assume that stdio.h does not declare or define any symbols referenced in the above source code, with the exception of printf. Assume that an int is 4 bytes in size and a long int is 8 bytes in size. // QUESTIONS: True or false: Both source code files can be compiled individually to object files without a compiler error In the above code, which variables(s) will the linker complain about as being undefined at link time? (Assume that the linker is capable of reporting all undefined variable references in one go) In the above code, how many bytes do you expect the size of the data segment in bar.o to be ______ In the above code, how many bytes do you expect the size of the bss segment in bar.o to be________
True b and c 8 4 1. All errors are link time errors. 2. b, c. b is declared external in both foo.c and bar.c but never defined. c is " 3. 8 bytes to hold f 4. 4 bytes to hold d
Which of the following segments have sizes that are determined statically (before the program is run): data stack heap text bss
True False False True True
Select all correct statements: In order to allocate space within a function, we can simply decrement the %rsp pointer. Recursive functions can be made more efficient though the use of "tail call elimination". When a new function is called with more than six arguments, the first six arguments are stored in special registers, while additional arguments are stored in the callee's stack frame. Buffer overflow attacks write more data into a buffer than it is capable of holding, thereby accessing memory outside of the buffer object. Writing many small, compartmentalized functions in C code instead of one large function always increases the runtime of the compiled program because each new function results in an explicit function call in Assembly. Recursive C functions are sometimes "transformed" into a loop-based implementation in assembly by the compiler in order to optimize the runtime of the program.
True True True True False True
Select all correct statements: According to the x86-64 calling convention, return values of functions are passed through the %rax register. The top of the stack is stored in the %rsp register. %eax refers to only the lower 32 bits of the %rax register. The content of a register is accessed in Assembly using the % prefix. As automatic lifetime objects are created, the stack pointer increases in value. We can access the contents of a register by dereferencing a pointer that stores its address.
True True True True False False
/ declarations int i, j, k[10] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; int *ip; char a, b, c[10] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; char *cp; void *vp; typedef struct stst {int i; char *p; } st; //assignment statements st x; ip = &k[4]; vp = ip; cp = &c[0]; x.p = cp + 3; x.i = 27; // Calculate: vp=&x;*(((st*)vp)->p);
14
Suppose that you use 1 bit for the sign, 3 bits for the exponent, and 14 bits for the mantissa and that you represent numbers in normalized notation. Assume that setting exponent bits to all 0s or 1s are special cases. What is the largest number that you can represent, assuming the bias from the previous question, truncated to the third decimal place? (Note that this is not the same as rounding, you are simply discarding the last digits)
15.999
// declarations int i, j, k[10] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; int *ip; char a, b, c[10] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; char *cp; void *vp; typedef struct stst {int i; char *p; } st; //assignment statements st x; ip = &k[4]; vp = ip; cp = &c[0]; x.p = cp + 3; x.i = 27; // Calculate: *(ip) + 6;
16
How many kilobytes do you need in order to represent the binary value corresponding to decimal number of 2^16383 + 2^8191 + 2^10?
2
Suppose that you had a number expressed in base 4. How many digits of the base-4 number would represent an individual digit of the equivalent base 16 number?
2
Fast Inverse Square Root (Text) One of the nice (or bad) things that C allows is pointer casting from data type to another. Let's see an example of why one would even do this and why C allows you to have a powerful and efficient program perhaps at the cost of portability and programmability.Inverse square root (1/x) is one of the operations that is repeatedly performed in a lot of areas. For example, in signal analyses (e.g. for normalizing a vector) and graphics (e.g. angles of incidence for lighting). These examples also run this function for a large number of times. In the graphics example, an inverse square root operation may need to be performed anywhere between 1000 to 10000 times per 15 ms, which continues to rise with the increasing graphic quality demanded by recent games and movies. However, this operation is quite costly. x here is a floating-point number, and the operation needs a square root and a divide on a floating-point. To give you an idea, a floating-point divide takes roughly 25 cycles while a floating-point square root can take over 50 cycles.Note that multiplications and additions in floating-point are cheap compared to division taking roughly 2-5 cycles. Also, multiplications and divisions by powers of 2 are also extremely cheap, since it simply involves addition or subtraction of the exponent.Below is the code for approximating the inverse square root used in Quake 3 Arena, a game best known for its 3D graphics, with some light edits to the comments - 1 :float Q_rsqrt( float number ) 2 :{ 3 : int32_t i; 4 : float x2, y; 5 : const float threehalfs = 1.5F; 6 : 7 : x2 = number * 0.5F; 8 : y = number; 9 : i = * ( int32_t * ) &y; // evil floating point bit level hacking 10: i = 0x5f3759df - ( i >> 1 ); // what the hugs? 11: y = * ( float * ) &i; 12: y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration, newton's approximation 13: // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed 14: 15: return y; 16:} You should note that int32_t and float are both 32 bits wide here. The number 0x5f3759df is a constant here used as an approximation for sqrt(2^(127)). By simply counting the number of operations involved here, you can see that this approximation extremely fast, compared to doing the sqrt and the division. We won't go through why this works (but you should be able to reason about it with your knowledge of floating-point representation). If you would like to know more, you can search for "Fast inverse square root algorithm" or even simply "0x5f3759df" to get an explanation for it. However, let's try to solve a working example of the algorithm for number=0.15625. The inverse sqrt of 0.15625 is approximately 2.52982. Question: Fast Inverse Square Root Part 7 For the variable evaluated in part 6, if the bit pattern is evaluated as an IEEE 32-bit floating-point number, what is the value of this number in decimal?
2.6149
// declarations int i, j, k[10] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; int *ip; char a, b, c[10] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; char *cp; void *vp; typedef struct stst {int i; char *p; } st; //assignment statements st x; ip = &k[4]; vp = ip; cp = &c[0]; x.p = cp + 3; x.i = 27; // Calculate: *(ip+2) + c[3];
28
Floating Point Numbers (Part 1) Suppose that you use 1 bit for the sign, 3 bits for the exponent, and 14 bits for the mantissa and that you represent numbers in normalized notation. Assume that setting exponent bits to all 0s or 1s are special cases. If you want to split the range of the exponent fields into one half that represents negative exponents, and another half that represents positive exponents (where 0 is counted as a negative number), what bias should you apply to the exponent?
3
Calculate the gate delay count to generate a CARRY OUT signal in a 1-bit full adder assuming that only 2-input gates are permitted
3, or 0
If 2^N bytes is a gigabyte, what is N?
30
long bar(long arg1, long arg2){ // some definition } long foo(long arg1, long arg2){ long temp1 = arg1 + 5; long temp2 = arg2 + 5; long temp3 = temp1 + 5; long temp4 = temp3 + 5; long temp5 = bar(temp3, temp4); long temp6 = temp1 * 2; return temp6; } In function foo, are there any opportunities for deadcode elimination? If yes, how many statements are dead?
4
If 2^N bytes is a terabyte, what is N?
40
If 2^N megabytes is an exabyte, what is N?
40
If 2^N terabytes is a yottabyte, what is N?
40
Suppose that you had a number expressed in base 32. How many digits of the equivalent binary number would represent an individual digit of the base 32 number?
5
Suppose that you have a 4-bit binary number. We refer to the LSB as bit 0, and the MSB as bit 3 Suppose that the LSB is 1 and the MSB is 0. Further, suppose that the overall impact of bits 1 and 2 is that they contribute an overall decimal value of 4. What is the overall decimal value of the number represented by this binary value?
5
If 2^N bytes is a petabyte, what is N?
50
There is an executable file on the Zoo, /c/cs323/ULA/valgrind-quiz. Use Valgrind to locate its memory leak. At what line number is `malloc` called, causing the memory leak?
53
/ declarations int i, j, k[10] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; int *ip; char a, b, c[10] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; char *cp; void *vp; typedef struct stst {int i; char *p; } st; //assignment statements st x; ip = &k[4]; vp = ip; cp = &c[0]; x.p = cp + 3; x.i = 27; // Calculate: *(ip-2);
6
Now, suppose that our ALU can support carry-lookahead but again, only 2-input gates are permitted. What is the gate delay count for a 4-bit adder?
6, or 0
If 2^N bytes is an exabyte, what is N?
60
Suppose that you have a 7-bit number represented in two's complement. What is the largest value that you can represent with this (write in decimal, human notation)?
63
#define NUMS (5) typedef struct abc { char* t; int** s; } abc; int main() { char* cities[] = {"New Haven", "New York City", "Boston"}; int vars[4] = {4, 5, 6, 7}; int nums[NUMS] = {1, 2, 3, 4, 5}; int* ptr[NUMS]; for (int i = 0; i < NUMS; i++) { ptr[i] = &nums[i]; } abc one; one.s = &(ptr[NUMS-3]); } // Calculate: vars[**(one.s)];
7
If 2^N bytes is an zettabyte, what is N?
70
If 2^N bytes is a yottabyte, what is N?
80
Suppose that you have a 60-bit number where all but bits 3 and the LSB are 0 (note again that we are 0-indexing from the LSB). What is the value of this number? Correct!
9
Which of the following result in link time errors: A global variable is not defined in any source code file but is declared and used in some source code files Multiple source code files declare a static variable with the same name A global variable is defined in one source code file and declared but not defined in all other source code files that use the variable
A global variable is defined in one source code file and declared but not defined in all other source code files that use the variable
x86 Assembly: Suppose that %rax holds the value of $0x111102AB before the following instruction is executed (shown in AT&T notation): %movl $0x1011, %eax What are the contents of %rax at the end of this instruction, in hexadecimal notation? Format your answer to start with $0x.
$0x1011
x86 Assembly: Suppose that %rax holds the value of $0x111102AB before the following instruction is executed (shown in AT&T notation): %mov $0x11, %ax What are the contents of %rax at the end of this instruction, in hexadecimal notation? Format your answer to start with $0x.
$0x11110011
Fast Inverse Square Root (Text) One of the nice (or bad) things that C allows is pointer casting from data type to another. Let's see an example of why one would even do this and why C allows you to have a powerful and efficient program perhaps at the cost of portability and programmability.Inverse square root (1/x) is one of the operations that is repeatedly performed in a lot of areas. For example, in signal analyses (e.g. for normalizing a vector) and graphics (e.g. angles of incidence for lighting). These examples also run this function for a large number of times. In the graphics example, an inverse square root operation may need to be performed anywhere between 1000 to 10000 times per 15 ms, which continues to rise with the increasing graphic quality demanded by recent games and movies. However, this operation is quite costly. x here is a floating-point number, and the operation needs a square root and a divide on a floating-point. To give you an idea, a floating-point divide takes roughly 25 cycles while a floating-point square root can take over 50 cycles.Note that multiplications and additions in floating-point are cheap compared to division taking roughly 2-5 cycles. Also, multiplications and divisions by powers of 2 are also extremely cheap, since it simply involves addition or subtraction of the exponent.Below is the code for approximating the inverse square root used in Quake 3 Arena, a game best known for its 3D graphics, with some light edits to the comments - 1 :float Q_rsqrt( float number ) 2 :{ 3 : int32_t i; 4 : float x2, y; 5 : const float threehalfs = 1.5F; 6 : 7 : x2 = number * 0.5F; 8 : y = number; 9 : i = * ( int32_t * ) &y; // evil floating point bit level hacking 10: i = 0x5f3759df - ( i >> 1 ); // what the hugs? 11: y = * ( float * ) &i; 12: y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration, newton's approximation 13: // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed 14: 15: return y; 16:} You should note that int32_t and float are both 32 bits wide here. The number 0x5f3759df is a constant here used as an approximation for sqrt(2^(127)). By simply counting the number of operations involved here, you can see that this approximation extremely fast, compared to doing the sqrt and the division. We won't go through why this works (but you should be able to reason about it with your knowledge of floating-point representation). If you would like to know more, you can search for "Fast inverse square root algorithm" or even simply "0x5f3759df" to get an explanation for it. However, let's try to solve a working example of the algorithm for number=0.15625. The inverse sqrt of 0.15625 is approximately 2.52982. // QUESTION: Fast Inverse Square Root Part 3 Given that number=0.15625, what is the bit pattern for the expression ( i >>1 ) after the execution of line 9 in the above code?
00011111000100000000000000000000
Fast Inverse Square Root (Text) One of the nice (or bad) things that C allows is pointer casting from data type to another. Let's see an example of why one would even do this and why C allows you to have a powerful and efficient program perhaps at the cost of portability and programmability.Inverse square root (1/x) is one of the operations that is repeatedly performed in a lot of areas. For example, in signal analyses (e.g. for normalizing a vector) and graphics (e.g. angles of incidence for lighting). These examples also run this function for a large number of times. In the graphics example, an inverse square root operation may need to be performed anywhere between 1000 to 10000 times per 15 ms, which continues to rise with the increasing graphic quality demanded by recent games and movies. However, this operation is quite costly. x here is a floating-point number, and the operation needs a square root and a divide on a floating-point. To give you an idea, a floating-point divide takes roughly 25 cycles while a floating-point square root can take over 50 cycles.Note that multiplications and additions in floating-point are cheap compared to division taking roughly 2-5 cycles. Also, multiplications and divisions by powers of 2 are also extremely cheap, since it simply involves addition or subtraction of the exponent.Below is the code for approximating the inverse square root used in Quake 3 Arena, a game best known for its 3D graphics, with some light edits to the comments - 1 :float Q_rsqrt( float number ) 2 :{ 3 : int32_t i; 4 : float x2, y; 5 : const float threehalfs = 1.5F; 6 : 7 : x2 = number * 0.5F; 8 : y = number; 9 : i = * ( int32_t * ) &y; // evil floating point bit level hacking 10: i = 0x5f3759df - ( i >> 1 ); // what the hugs? 11: y = * ( float * ) &i; 12: y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration, newton's approximation 13: // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed 14: 15: return y; 16:} You should note that int32_t and float are both 32 bits wide here. The number 0x5f3759df is a constant here used as an approximation for sqrt(2^(127)). By simply counting the number of operations involved here, you can see that this approximation extremely fast, compared to doing the sqrt and the division. We won't go through why this works (but you should be able to reason about it with your knowledge of floating-point representation). If you would like to know more, you can search for "Fast inverse square root algorithm" or even simply "0x5f3759df" to get an explanation for it. However, let's try to solve a working example of the algorithm for number=0.15625. The inverse sqrt of 0.15625 is approximately 2.52982. // QUESTIONS!!!!!!! Fast Inverse Square Root Part 1 Given that number=0.15625, what is the bit pattern for the variable y and i at line 9 in the above code?
00111110001000000000000000000000
Fast Inverse Square Root (Text) One of the nice (or bad) things that C allows is pointer casting from data type to another. Let's see an example of why one would even do this and why C allows you to have a powerful and efficient program perhaps at the cost of portability and programmability.Inverse square root (1/x) is one of the operations that is repeatedly performed in a lot of areas. For example, in signal analyses (e.g. for normalizing a vector) and graphics (e.g. angles of incidence for lighting). These examples also run this function for a large number of times. In the graphics example, an inverse square root operation may need to be performed anywhere between 1000 to 10000 times per 15 ms, which continues to rise with the increasing graphic quality demanded by recent games and movies. However, this operation is quite costly. x here is a floating-point number, and the operation needs a square root and a divide on a floating-point. To give you an idea, a floating-point divide takes roughly 25 cycles while a floating-point square root can take over 50 cycles.Note that multiplications and additions in floating-point are cheap compared to division taking roughly 2-5 cycles. Also, multiplications and divisions by powers of 2 are also extremely cheap, since it simply involves addition or subtraction of the exponent.Below is the code for approximating the inverse square root used in Quake 3 Arena, a game best known for its 3D graphics, with some light edits to the comments - 1 :float Q_rsqrt( float number ) 2 :{ 3 : int32_t i; 4 : float x2, y; 5 : const float threehalfs = 1.5F; 6 : 7 : x2 = number * 0.5F; 8 : y = number; 9 : i = * ( int32_t * ) &y; // evil floating point bit level hacking 10: i = 0x5f3759df - ( i >> 1 ); // what the hugs? 11: y = * ( float * ) &i; 12: y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration, newton's approximation 13: // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed 14: 15: return y; 16:} You should note that int32_t and float are both 32 bits wide here. The number 0x5f3759df is a constant here used as an approximation for sqrt(2^(127)). By simply counting the number of operations involved here, you can see that this approximation extremely fast, compared to doing the sqrt and the division. We won't go through why this works (but you should be able to reason about it with your knowledge of floating-point representation). If you would like to know more, you can search for "Fast inverse square root algorithm" or even simply "0x5f3759df" to get an explanation for it. However, let's try to solve a working example of the algorithm for number=0.15625. The inverse sqrt of 0.15625 is approximately 2.52982. Question: Fast Inverse Square Root Part 6 Given that number=0.15625, what is the bit pattern for the variable i after the execution of line 10 in the above code?
01000000001001110101100111011111
Convert two's complement 0xC521 to binary. Your binary value should remain in two's complement. In order to answer this question, carefully consider whether the fact that the values are in two's complement affects how you approach this answer. Please enter the answer pre-pended by 0b (eg, 0b1101)
0b1100010100100001
Convert two's complement 0xC521 to octal. The octal value should remain in two's complement. In order to answer this question, carefully consider whether the fact that the values are in two's complement affects how you approach this answer. Remember to format the answer with 0o.
0o142441
What is the decimal value of 0d27 in hexadecimal notation? Give your answer in the form 0xVALUE, where the string '0x' indicates that the number is in hexadecimal, and all characters are capitalized. Note also that the form 0dValue, with the prefix '0d' indicates decimal notation.
0x1B
Convert -512 (decimal) into hexadecimal with sign and magnitude representation. Use 16 bits. Remember to format the answer with 0x.
0x8200
What is the hexadecimal value of 0o345? Give your answer in the form 0xVALUE, where the string '0x' indicates that the number is in hexadecimal, and all characters are capitalized. Note also that the form 0oValue, with the prefix '0o' indicates octal notation.
0xE5
Consider a program written to work similar to an Operating System loader. This program runs like a normal program, understands and parses ELF files, can request memory from the OS at specific locations, and even change the protection of this memory to match the expected permission of the segment. The loader program uses some of the following functions and data structures. Some commented function declarations and struct definitions are provided here to aid your understanding of the code: // Allocates n bytes of memory within current process void* allocate(size_t n); // Set hardware enforced permissions perm for memory locations // [a,b) within current process void protect(void* a, void* b, permissions_t perm); // Copies n bytes from src to dest. Returns dest. // All addresses are within the current process. void* memcpy(void* dest, void* src, size_t n); // Runs the loaded program by finding and jumping to the starting point void run_program(const elf_contents* s); // Represents a single elf segment struct elf_segment { size_t size; // segment size in bytes permissions_t permissions; // segment permissions void* data; // pointer to segment's data void* loc; // points to where segment is copied to } The loader program follows the broad steps given in the code below: loader.c main(char * file){ elf_contents elf = parse_elf(file); for(i = 0 ; i < elf->num_segs ; i++) {void* mem = allocate(elf->seg[ i ]->size); // line A void* end = (char*) mem + elf->seg[ i ]->size; // line B protect(mem, end, elf->seg[ i ]->permissions); // line C memcpy(mem, elf->seg[ i ]->data, elf->seg [ i ]->size); // line D elf->seg[ i ]->loc = mem; // line E } set_up_stack(); // line F set_up_heap(); // line G run_program(&elf); return 1;// never reached} Assuming a correctly formatted ELF program with all common segments, answer the following questions.Identify each line by using the letter provided in the comments within the source code. For example, the identifier for the line ending in "// line C" is C. // Questions: Which line will cause a permissions fault in this program? Which line is the direct cause of the permissions fault? Which of the following changes need to be made to fix the permissions fault? [Need to reorder a few lines]
D - Line D will cause a permissions fault for read-only data C - Line C is the reason for the permissions fault Need to reorder a few lines - Need to reorder line C and D