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:
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
NaNNaN
+
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?
0.343750.0097656
25-28.0
0 0101 0110 0000 1011 1011 110
Representation -> Number
A: Bias is 7. (2(4-1)-1)
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 0010 0110 0011 1010 111
Typecasting
• What is 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
EIP
Registers
CPU Memory
Object CodeProgram Data
Addresses
Data
Instructions
Stack
ConditionCodes
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 FormD(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; t = t - 1; u = 16*t; return -u*t;}
Method 1
foo:pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%edx movl 12(%ebp),%eax
movl $3, %ecximull %ecx,%edxmovl $6, %ecximull %ecx,%eaxsubl %eax,%edxdecl %edxmovl %edx,%eaxsall $4,%eaximull %edx,%eaxnegl %eax
movl %ebp,%esppopl %ebpret
Example 1: Simple Stuff (cont.)
Method 2foo:
pushl %ebp movl %esp,%ebp
movl 8(%ebp),%edx movl 12(%ebp),%eax
leal (%edx,%edx,2),%edxleal (%eax,%eax,2),%eaxaddl %eax,%eaxsubl %eax,%edxdecl %edxmovl %edx,%eaxsall $4,%eaximull %edx,%eaxnegl %eax
movl %ebp,%esppopl %ebpret
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
int absdiff(int x, int y){ if (x>=y) return x-y; else return y-x;}
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
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; int i=0; for (i=0; i<size; i++) sum += array[i]; return sum;}
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
Example 4: Jump Tables
#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]);
switch(operation) { case 0: printf("Sum is: %d\n", x + y); break; case 1: printf("Diff is: %d\n", x - y); break; case 2: printf("Mult is: %d\n", x * y); break; case 3: printf("Div is: %d\n", x / y); break; case 4: printf("Mod is: %d\n", x % y); default: printf("Unknown command\n"); break; }
return 0;}
A0: mystery:A1: movl 8(%ebp), %edxA2: movl $0x0, %eaxA3: cmpl $0x0, 12(%ebp)A4: je .L11A5: .L8A6: cmpl $0x0, 12(%ebp)A7: jle .L9A8: add %edx, %eaxA9: decl 12(%ebp)A10: jmp .L10A11:.L9A12: sub %edx, %eaxA13: incl 12(%ebp)A14:.L10A15: compl $0x0, 12(%ebp)A16: jne .L8A17:.L11A18: mov %ebp, %espA19: pop %ebpA20: ret
Example 5
# Get x# Set result = 0# Compare y:0# If(y == 0) goto Done# Loop:# Compare y:0# If(y <= 0) goto Negative# result += x# y—# goto Check# Negative:# result -= x# y++# Check:# Compare y:0# If(y != 0) goto Loop# Done:## Cleanup#
int multiply(int x, int y){ int result = 0; while (y != 0) { if (y > 0) { result += x; y--; } else { result -= x; y++; } } return result;}
A0: mystery:A1: movl 8(%ebp), %edxA2: movl $0x0, %eaxA3: cmpl $0x0, 12(%ebp)A4: je .L11A5: .L8A6: cmpl $0x0, 12(%ebp)A7: jle .L9A8: add %edx, %eaxA9: decl 12(%ebp)A10: jmp .L10A11:.L9A12: sub %edx, %eaxA13: incl 12(%ebp)A14:.L10A15: compl $0x0, 12(%ebp)A16: jne .L8A17:.L11A18: mov %ebp, %espA19: pop %ebpA20: ret
Example 5
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
A0: mystery2:A1: push %ebpA2: movl %esp, %ebpA3: movl 8(%ebp), %ebxA4: movl 16(%ebp), %edxA5: movl $0xffffffff, %eaxA6: movl $0x0, 0xfffffff4(%ebp)A7: decl %edxA8: compl %edx, %ecxA9: jg .L13A10: .L9A11: add %edx, %ecxA12: sarl $0x1, %ecxA13: cmpl 12(%ebp), (%ebx,%ecx,4)A14: jge .L10A15: incl %ecxA16: movl %ecx, 0xfffffff4(%ebp)A17: jmp .L12
Challenge Problem: Code
A18: .L10A19: cmpl (%ebx,%ecx,4), 12(%ebp)A20: jle .L11A21: movl %ecx, %edxA22: decl %edxA23: jmp .L12A24: .L11A25: movl %ecx, %eaxA26: jmp .L13A27: .L12A28: cmpl %edx, 0xfffffff4A29: jle .L9A30: .L13A31: movl %ebp, %espA32: pop %ebpA33: ret
Answer: Binary Search# 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: Answer
A0: mystery2:A1: push %ebpA2: movl %esp, %ebpA3: movl 8(%ebp), %ebxA4: movl 16(%ebp), %edxA5: movl $0xffffffff, %eaxA6: movl $0x0, 0xfffffff4(%ebp)A7: decl %edxA8: compl %edx, %ecxA9: jg .L13A10: .L9A11: add %edx, %ecxA12: sarl $0x1, %ecxA13: cmpl 12(%ebp), (%ebx,%ecx,4)A14: jge .L10A15: incl %ecxA16: movl %ecx, 0xfffffff4(%ebp)A17: jmp .L12
Challenge Problem (continued)
# 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#
A18: .L10A19: cmpl (%ebx,%ecx,4), 12(%ebp)A20: jle .L11A21: movl %ecx, %edxA22: decl %edxA23: jmp .L12A24: .L11A25: movl %ecx, %eaxA26: jmp .L13A27: .L12A28: cmpl %edx, 0xfffffff4A29: jle .L9A30: .L13A31: movl %ebp, %espA32: pop %ebpA33: ret
Challenge Problemint 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; else return Mid; /* Found */ } return -1;}