15-213 Recitation 2 – 2/4/02 Outline Floating Point Typecasting Machine Model Assembly Programming Structure Addressing Modes L2 Practice Stuff Mengzhi Wang e-mail: mzwang@cs.cmu.edu Office Hours: Thursday 1:30 – 3:00 Wean Hall 3108
Floating Point (Better known as “I’m going to kill the person that thought this up”) IEEE Floating Point Standard notation Tons of features we won’t look at Floating Point at a bit level: s – sign bit (S) exp – exponent (maps to E, has e bits) frac – significand (maps to M, has f bits) Numerical Equivalent: –1s M 2E “Normalized” and “Denormalized” encoding s exp frac
“Normalized” Encoding exp 0 and exp 111…1 If exp = 111…1, it’s or NAN E = exp – B B is the “Bias” Usually 2e-1 – 1, but can be different exp: Unsigned integer value [1, 2e – 1] M = 1.{frac} {frac} are the bits of frac frac is a fractional binary number Normalized Numbers have range [21-B, 2B+1) And their negatives
“Denormalized” Encoding exp = 0 E = -B+1 M = 0.{frac} Denormalized Numbers have Range [0, 21-B) And their negatives NaN + 0 +Denorm +Normalized -Denorm -Normalized +0
FP Examples 8 bit FP, 1 bit sign, 4 bit exponent, 3 bit significand Q: What is the bias? A: Bias is 7. (2(4-1)-1) 0 0101 011 0 0000 101 1 1011 110 Representation -> Number 0.34375 0.009765625 -28.0
Number -> Representation More FP Examples 8 bit FP, 1 bit sign, 4 bit exponent, 3 bit significand, Bias of 7 Number -> Representation 9 .6 -15 0 1010 001 0 0110 001 1 1010 111
Typecasting What is typecasting? How to typecasting? Some types can be converted (or typecast) to others in C. Typecasting is often unavoidable and essential. How to typecasting? Assume: x has type type_a y has some type that can be cast to type_a cast y to type_a and assign it to x: x = (type_a)y; What types can be cast? All primitive types in C can be cast to another. Pointers can be also be cast.
Typecasting Examples Casting integers from large size data types to small ones C integer types long, int, short, char Possible overflow Occurs when the data is out of the range of the small data type Normal: int a = 1024; short s = (short)a; -or- short s = a; -> S = 1024; Overflow: int x = 0x0034a140; short s = x; -> s = 0xa140 = -24256
Typecasting Examples Casting integers from small size data types to large ones Sign Extension: the sign bit is copied to every higher bit for signed types Positive numbers: short s = 0xf0; int i=s; unsigned u = s; -> i = 240 -> u = 240 Negative numbers: signed char c = 0xf0; unsigned char uc = 0xf0; int i = c; unsigned c2u = c; unsigned uc2u = uc; -> i = -16, NOT 240 -> c2u = 4294967280 -> uc2u = 240
Typecasting with FPs Casting floating point numbers to integers Rounded to the nearest integer value Example 1: float a = -3.5; int i = (int)a; -> i = -3 (note round to zero behavior) Example 2: int i = 4; double x = (double)i; int root = (int)sqrt(x); -> x = 4.0 ->root = 2
Typecasting with FPs (cont.) Casting integers to floating point numbers Some large integers can not be represented exactly in floating point. Rounding error example: unsigned int i = 0xfffffff0; float f = (float)i; double d = (double)i; -> i = 4294967280 -> f = 4294967296.0 -> d = 4294967280.0
Machine Model CPU Memory Addresses Registers E I P Object Code Program Data Data Condition Codes Instructions Stack
Special Registers %eax Return Value %eip Instruction Pointer %ebp Base (Stack Frame) Pointer %esp Stack Pointer
Assembly Programming: Structure Function Setup Save Old Base Pointer (pushl %ebp) Set up own base pointer (movl %esp, %ebp) Note that this saves the old stack pointer Save any registers that could be clobbered Where? Function Body Operations on data, loops, function calls
Assembly Programming: Structure Function Cleanup Return value placed in %eax What about returning larger values? (structs, doubles, etc.) Restore Caller’s Stack Pointer (movl %ebp, %esp) Restore Old Base Pointer (popl %ebp) Return Where does it return to?
Assembly Programming: Simple Addressing Modes Examples (R) Mem[R] $10(R) Mem[R + 10] $0x10(R) Mem[R + 16]
Assembly Programming: Indexed Addressing Modes Generic Form D(Rb, Ri, S) Mem[Reg[Rb]+S*Reg[Ri]+ D] Examples (Rb,Ri) Mem[Reg[Rb]+Reg[Ri]] D(Rb,Ri) Mem[Reg[Rb]+Reg[Ri]+D] (Rb,Ri,S) Mem[Reg[Rb]+S*Reg[Ri]]
Example 1: Simple Stuff int foo(int x, int y) { int t, u; t = 3*x-6*y; Method 1 foo: pushl %ebp movl %esp,%ebp movl 8(%ebp),%edx movl 12(%ebp),%eax movl $3, %ecx imull %ecx,%edx movl $6, %ecx imull %ecx,%eax subl %eax,%edx decl %edx movl %edx,%eax sall $4,%eax imull %edx,%eax negl %eax movl %ebp,%esp popl %ebp ret int foo(int x, int y) { int t, u; t = 3*x-6*y; t = t - 1; u = 16*t; return -u*t; }
Example 1: Simple Stuff (cont.) Method 2 foo: pushl %ebp movl %esp,%ebp movl 8(%ebp),%edx movl 12(%ebp),%eax leal (%edx,%edx,2),%edx leal (%eax,%eax,2),%eax addl %eax,%eax subl %eax,%edx decl %edx movl %edx,%eax sall $4,%eax imull %edx,%eax negl %eax movl %ebp,%esp popl %ebp ret int foo(int x, int y) { int t, u; t = 3*x-6*y; t = t - 1; u = 16*t; return -u*t; }
Example 2: More Simple Stuff absdiff: pushl %ebp movl %esp,%ebp movl 8(%ebp),%edx movl 12(%ebp),%eax cmpl %eax,%edx jl .L3 subl %eax,%edx movl %edx,%eax jmp .L6 .L3: subl %edx,%eax .L6: movl %ebp,%esp popl %ebp ret int absdiff(int x, int y) { if (x>=y) return x-y; else return y-x; } If condition Then part Else part
Example 3: Backwards get_sum: pushl %ebp movl %esp,%ebp pushl %ebx movl 8(%ebp),%ebx movl 12(%ebp),%ecx xorl %eax,%eax movl %eax,%edx cmpl %ecx,%eax jge .L4 .L6: addl (%ebx,%edx,4),%eax incl %edx cmpl %ecx,%edx jl .L6 .L4: popl %ebx movl %ebp,%esp popl %ebp ret # ebx = 1st arg # ecx = 2nd arg # eax = 0 # edx = 0 # # if (ecx >= 0) goto L4 # eax += Mem[ebx+edx*4] # edx ++ # if (ecx < edx) goto L6
Example 3: Answer int get_sum(int * array, int size) { int sum = 0; pushl %ebp movl %esp,%ebp pushl %ebx movl 8(%ebp),%ebx movl 12(%ebp),%ecx xorl %eax,%eax movl %eax,%edx cmpl %ecx,%eax jge .L4 .L6: addl (%ebx,%edx,4),%eax incl %edx cmpl %ecx,%edx jl .L6 .L4: popl %ebx movl %ebp,%esp popl %ebp ret int get_sum(int * array, int size) { int sum = 0; int i=0; for (i=0; i<size; i++) sum += array[i]; return sum; }
Example 4: Jump Tables switch(operation) { case 0: printf("Sum is: %d\n", x + y); break; case 1: printf("Diff is: %d\n", x - y); case 2: printf("Mult is: %d\n", x * y); case 3: printf("Div is: %d\n", x / y); case 4: printf("Mod is: %d\n", x % y); default: printf("Unknown command\n"); } return 0; #include <stdio.h> int main(int argc, char *argv[]) { int operation, x, y; if(argc < 4) { printf("Not enough arguments\n"); exit(0); } operation = atoi(argv[1]); x = atoi(argv[2]); y = atoi(argv[3]);
Example 5 A0: mystery: A1: movl 8(%ebp), %edx A2: movl $0x0, %eax A3: cmpl $0x0, 12(%ebp) A4: je .L11 A5: .L8 A6: cmpl $0x0, 12(%ebp) A7: jle .L9 A8: add %edx, %eax A9: decl 12(%ebp) A10: jmp .L10 A11:.L9 A12: sub %edx, %eax A13: incl 12(%ebp) A14:.L10 A15: compl $0x0, 12(%ebp) A16: jne .L8 A17:.L11 A18: mov %ebp, %esp A19: pop %ebp A20: ret # Get x # Set result = 0 # Compare y:0 # If(y == 0) goto Done # Loop: # If(y <= 0) goto Negative # result += x # y— # goto Check # Negative: # result -= x # y++ # Check: # If(y != 0) goto Loop # Done: # # Cleanup
Example 5 int multiply(int x, int y) { int result = 0; A0: mystery: A1: movl 8(%ebp), %edx A2: movl $0x0, %eax A3: cmpl $0x0, 12(%ebp) A4: je .L11 A5: .L8 A6: cmpl $0x0, 12(%ebp) A7: jle .L9 A8: add %edx, %eax A9: decl 12(%ebp) A10: jmp .L10 A11:.L9 A12: sub %edx, %eax A13: incl 12(%ebp) A14:.L10 A15: compl $0x0, 12(%ebp) A16: jne .L8 A17:.L11 A18: mov %ebp, %esp A19: pop %ebp A20: ret int multiply(int x, int y) { int result = 0; while (y != 0) { if (y > 0) { result += x; y--; } else { result -= x; y++; return result;
Challenge Problem A function with prototype int mystery2(int *A, int x, int N) is compiled into the assembly on the next page. Hint: A is an array of integers, and N is the length of the array. What is this mystery function computing?
Challenge Problem: Code A0: mystery2: A1: push %ebp A2: movl %esp, %ebp A3: movl 8(%ebp), %ebx A4: movl 16(%ebp), %edx A5: movl $0xffffffff, %eax A6: movl $0x0, 0xfffffff4(%ebp) A7: decl %edx A8: compl %edx, %ecx A9: jg .L13 A10: .L9 A11: add %edx, %ecx A12: sarl $0x1, %ecx A13: cmpl 12(%ebp), (%ebx,%ecx,4) A14: jge .L10 A15: incl %ecx A16: movl %ecx, 0xfffffff4(%ebp) A17: jmp .L12 A18: .L10 A19: cmpl (%ebx,%ecx,4), 12(%ebp) A20: jle .L11 A21: movl %ecx, %edx A22: decl %edx A23: jmp .L12 A24: .L11 A25: movl %ecx, %eax A26: jmp .L13 A27: .L12 A28: cmpl %edx, 0xfffffff4 A29: jle .L9 A30: .L13 A31: movl %ebp, %esp A32: pop %ebp A33: ret
Challenge Problem: Answer Answer: Binary Search A0: mystery2: A1: push %ebp A2: movl %esp, %ebp A3: movl 8(%ebp), %ebx A4: movl 16(%ebp), %edx A5: movl $0xffffffff, %eax A6: movl $0x0, 0xfffffff4(%ebp) A7: decl %edx A8: compl %edx, %ecx A9: jg .L13 A10: .L9 A11: add %edx, %ecx A12: sarl $0x1, %ecx A13: cmpl 12(%ebp), (%ebx,%ecx,4) A14: jge .L10 A15: incl %ecx A16: movl %ecx, 0xfffffff4(%ebp) A17: jmp .L12 # Set up # # ebx = Array A # edx = High = N # result = -1 # Low = 0 # ecx = Mid = Low # High— # Compare Low:High # If Low > High goto Done # Loop: # Mid += High # Mid /= 2 # Compare A[Mid]:X # If >=, goto High # Mid++ # Low = Mid # goto Check
Challenge Problem (continued) A19: cmpl (%ebx,%ecx,4), 12(%ebp) A20: jle .L11 A21: movl %ecx, %edx A22: decl %edx A23: jmp .L12 A24: .L11 A25: movl %ecx, %eax A26: jmp .L13 A27: .L12 A28: cmpl %edx, 0xfffffff4 A29: jle .L9 A30: .L13 A31: movl %ebp, %esp A32: pop %ebp A33: ret # High: # Compare X:A[Mid] # If <=, goto Found # High = Mid # High— # goto Check # Found: # Result = Mid # goto Done # Check: # Compare Low:High # If <=, goto Loop # Done: # # Cleanup
Challenge Problem int binsearch(int *A, int X, int N) { int Low, Mid, High; Low = 0; High = N - 1; while ( Low <= High ) { Mid = ( Low + High ) / 2; if ( A[ Mid ] < X ) Low = Mid + 1; else if ( A[ Mid ] > X ) High = Mid - 1; return Mid; /* Found */ } return -1;