- logistics: what's on the exam - lecture, lab, homeworks, readings, EXCEPT - command line stuff - no writing HCL; no asking what's valid or invalid HCL - no names of built-in signals or constants - how much reading code - some assembly and C - not more than ~5 or 6 lines of assembly; ~1 to 3 lines of C - floating point? not on the exam - in class, during class time, 75 minutes - what's happening in lab - lab is exam review - we aren't checking attendence - ways to study - best practice is prior exams (caveat: some questions aren't relevant anymore, or aren't written well) - also good: prior quizzes, ? textbook exercises; - make your own problems and solve them - F2016 #6 --- signed/unsigned comparison - F2016 #16 --- ALU and registers circuit - object files - assembly file: contains assembly code w/ labels --- within instructions and marking instructions contains data (initial value of global variables, constants, etc.) - object file: contains machine code for the assembly w/ placeholders for labels within insgtructions w/ symbol table of labels that mark an instruction or mark data (e.g. a string constant) contains constant data from assembly file - executable file: contains machine code and initial data to load directly into memory - placeholders replaced with actual addresses needed - placing MUXes - general strategy: what do my inputs need to be? - if there are multiple choices, there needs to be a MUX - if there's an additional choice, need a MUX with more inputs - hypothetical: adding a new immovq instruction; what changes about MUXes? - immovq $100, 0(%rax) --- writes to memory at address %rax + 0 the value 100 - value input to the data memory: before adding immovq: nop, add, ... --- nothing rmmovq, pushq --- value from a register (register file output) call --- PC + 10 --> must already have a MUX after adding immovq: everything else + immovq --- constant from the instruction (part of what the instruction memory is outputting) not already a possible input; need to add something to the MUX herek - S2017 #20 --- extracting rB from instruction in C unsigned char *instr; // [most sig 4 bits of byte 0: icode] [least sig 4 bits of byte 0: ifun] { [most sig 4 bits of byte 1: rA] [least sig 4 bits of byte 1: rB] <--- } byte 1: -- instr[1] 00001111 binary = 0x0F ^^^^ don't keep ^^^^ keep (instr[1] >> 0) & 0x0F --> instr[1] & 0x0F abcdefgh >> 0 --> abcdefgh & 0x0F 00001111 --> 0000efgh - bitwise true/false strategies - and overflow (x << 2) ? (x | y) x = y = 0: >? 0 x = y = 1: 1 <--> 1 x = 0; y = 1 0 <--> 1 <= if sign bit is 0 - look for counterexamples (x >> 2) --- what happens if all the interesting bits of x are shifted away? --- can x be negative? what happens if x is some negative number (e.g. -1) - remember that -x == ~x + 1 - lists in C - sentinel terminated arrays -- can't store everything (sentinel valyue) pointer plus <--- on stack/registers/etc. memory with space for N + 1 values <--- dynamically allocated - "ranges" pointer plus <--- on stack/registers/etc. a length plus <--- on stack/registers/etc. memory with space for N values <--- dynamically allocated - linked lists pointer plus <--- on stack/registers/etc. N instances of memory with space for a value and a pointer ^ dynamically allocatedk - Y86 versus X86 - one type of operands for each instruction - e.g. addq only takes registers - e..g mrmovq only takes register + displacement(register) - seperate mov instructions - RISC versus CISC - key idea: RISC simplifies hardware design - fixed-length instructions ---> easier to fetch, decode, etc. - values in the same parts of instructions --> easier to decode - fewer instructions ---> easier to implement all parts of the CPU - simpler instructions --> easier to implement - few ways to specify operands - no doing computation and memory access in the same instruction (e.g. all stack manipulation instructions) - no writing multiple results from one instruction (e.g. popq) - usually more registers - way of using extra space in HW - better performance even though most instructions don't take memory operands - ternary operator x ? y : z if (x) { y } else { z } (but results in the value) - Q9 S2017 --- reading Y86 and machine code - undefined behavior in C - what is it? compiler can do anything - cases where people who defined what C is don't care - example from lecture: x + 1 overflowing (x is signed) - compiler could optimize (x + 1) > x - other common examples: - anything that causes segfault (out of bounds of array; reading freed memory; etc.) - shifting by more than the width of a value