15-213 Recitation 2 – 2/11/02 Outline Stacks & Procedures Homogenous Data Arrays Nested Arrays Structured Data structs / unions Arrays of structs Anusha e-mail: anusha@andrew.cmu.edu Office Hours: Tuesday, 11:30-1:00 Wean Cluster 52xx Reminders Lab 2: Tuesday, 11:59
Stacks Grows down Stores local variables that can’t fit in registers Stores arguments and return addresses %esp Stack Pointer Points to the top value on the stack %ebp Base Pointer Points to a function’s stack frame pushl Decrements, then places value popl ‘Returns’ value, then increments
Stack Frames Abstract partitioning of the stack Caller Frame Abstract partitioning of the stack Each Frame contains the state for a single function instant Arguments Frame Pointer (%ebp) Return Addr Old %ebp Saved Registers Local Variables Argument Build Stack Pointer (%esp)
Procedures call: Caller Responsibilities Arguments (pushl) In what order? Return Address (done by call) ret: Callee Responsibilities Save Registers (especially %ebp) Set up Stack Frame Return value in %eax
Problem 1: Call Chain void absdiff(int *result, int x, int y) { int z; if (x >= y) z = x - y; else z = y - x; *result = z; return; } int main() { int result; int x,y; x = 5; y = -3; absdiff(&result, x, y); printf("|(%d) - (%d)| = %d\n", x, y, result); return 0; }
Problem 1: Answer <main>: push %ebp mov %esp,%ebp sub $0x18,%esp Old %ebp <main>: push %ebp mov %esp,%ebp sub $0x18,%esp movl $0x5,-8(%ebp) movl $0xfffffffd, -12(%ebp) add $0xfffffffc,%esp mov -12(%ebp),%eax push %eax mov -8(%ebp),%eax lea -4(%ebp),%eax call <absdiff> %ebp result 5 -3 %esp -3 5 &result Rtn Address %esp
Problem 1: Answer <absdiff>: push %ebp mov %esp,%ebp sub $0x18,%esp mov 0xc(%ebp),%eax cmp 0x10(%ebp),%eax jl .L1 mov 0x10(%ebp),%edx mov %eax,%ecx sub %edx,%ecx jmp .L2 .L1 mov 0x10(%ebp),%eax mov 0xc(%ebp),%edx .L2 mov 0x8(%ebp),%eax mov %ecx,(%eax) mov %ebp,%esp pop %ebp ret * %esp -3 5 &result Rtn Address Old %ebp %ebp %esp
Problem 1: Answer <main>: ….. add $0x10, %esp mov -4(%ebp),%eax Old %ebp %ebp %esp <main>: ….. add $0x10, %esp mov -4(%ebp),%eax push %eax mov -12(%ebp),%eax mov -8(%ebp),%eax push $0x80484d8 call <printf> mov %ebp,%esp pop %ebp ret result 5 -3 %esp result -3 5 $0x80484d8 Rtn Address
Problem 2: Recursion With the following code, what does the stack look like if we call fib(1, 1, 0) and reach the point where if(n==0) holds true? int fib(int n, int next, int result) { if(n == 0) return result; return fib(n - 1, next + result, next); }
Problem 2: Answer 0 ; third argument to fib 1 ; second 1 ; first ret ; call fib oldebp ; <--- ebp of fib’s caller 1 ; <--- push result 1 ; <--- next + result 0 ; <--- n - 1 oldebp
Homogenous Data: Arrays Allocated as contiguous blocks of memory Address Computation Examples int cmu[5] = {…} cmu begins at memory address 40 cmu[0] 40 + 4*0 = 40 cmu[3] 40 + 4*3 = 52 cmu[-1] 40 + 4*-1 = 36 cmu[15] 40 + 4*15 = 100
Problem 3: Arrays get_sum: pushl %ebp movl %esp,%ebp pushl %ebx movl 8(%ebp),%ebx # ebx = 1st arg (array A) movl 12(%ebp),%ecx # ecx = 2nd arg (size) xorl %eax,%eax # eax = 0 movl %eax,%edx # edx = 0 cmpl %ecx,%edx # jge .L4 # if (0 >= ecx) goto L4 .L6: addl (%ebx,%edx,4),%eax # eax += Mem[ebx+edx*4] incl %edx # edx ++ jl .L6 # if (edx < ecx) goto L6 .L4: popl %ebx movl %ebp,%esp popl %ebp ret
Problem 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; }
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 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, %ecx A7: decl %edx A8: compl %edx, %ecx A9: jg .L13
Challenge Problem (continued) 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
Challenge Problem (more code) 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: Binary Search # Set up A0: mystery2: # # ebx = Array A # edx = High = N # result = -1 # Low = 0 # ecx = Mid = Low # High— # Compare Low:High # If Low > High goto Done 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, %ecx A7: decl %edx A8: compl %edx, %ecx A9: jg .L13
Challenge Problem (continued) 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 # Loop: # Mid += High # Mid /= 2 # Compare A[Mid]:X # If >=, goto High # Mid++ # Low = Mid # goto Check # High: # Compare X:A[Mid] # If <=, goto Found # High = Mid # High—
Challenge Problem (more code) # Found: # Result = Mid # goto Done # Check: # Compare Low:High # If <=, goto Loop # Done: # # Cleanup 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 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;
Problem 4: Nested arrays int main(int argc, char **argv) { int i,j,r=0; for (i=0; i<argc; i++) { j=0; while(argv[i][j] != '\0') { r ^= argv[i][j]; j++; } return r;
Problem 4: Answer .L9: main: movsbl (%ecx,%edx),%eax pushl %ebp xorl %eax,%esi incl %ecx cmpb $0,(%ecx,%edx) jne .L9 .L5: incl %ebx cmpl 8(%ebp),%ebx jl .L6 .L4: movl %esi,%eax popl %ebx popl %esi popl %edi movl %ebp,%esp popl %ebp ret main: pushl %ebp movl %esp,%ebp pushl %edi pushl %esi pushl %ebx movl 12(%ebp),%edi xorl %esi,%esi xorl %ebx,%ebx cmpl 8(%ebp),%ebx jge .L4 .L6: xorl %ecx,%ecx movl (%edi,%ebx,4),%eax cmpb $0,(%eax) je .L5 movl %eax,%edx
structs and unions Organize data structs store multiple elements, unions store a single element at a time Members of a union change how you look at data unions used for mutually exclusive data
Alignment Contiguous areas of memory Each block is aligned Why? Size is a multiple of a base value “Base value” is the largest alignment of data types in structure Why? Efficient load/store from memory Virtual Memory paging This applies to any variable type
Structure of a struct Find largest alignment Size of structure must be a multiple of this For each element e (top to bottom): Find alignment of e Starting offset must be a multiple of this Pad previous element with empty space until alignment matches Allocate alignment worth of space to e Pad last element with empty space until alignment of structure matches Note this isn’t optimal!
Structure of a union Find largest alignment Allocate this much space Size of structure must be a multiple of this Allocate this much space Examples struct one { union two { int i; int i; double d; double d; char c[2]; char c[2]; }
Problem 5: Structs .LC0: #define MAX_STRING 20 .string "Jack" .LC1: .string "Black" .LC2: .string "12345ZXY" .align 32 .LC3: .string "Name : %s %s\nID : %s\nAge : %i\n“ main: pushl %ebp movl %esp, %ebp subl $88, %esp subl $4, %esp pushl $5 pushl $.LC0 leal -72(%ebp), %eax pushl %eax call strncpy addl $16, %esp pushl $6 pushl $.LC1 addl $20, %eax call strncpy #define MAX_STRING 20 #struct student #{ # char first [ MAX_STRING ]; # char last [ MAX_STRING ]; # char id [ MAX_STRING ]; # int age; #}; # struct student s1; # struct student *s2; # strncpy(s1.first, fName, # sizeof(fName)); # strncpy(s1.last, lName, # sizeof(lName));
Problem 5: Structs addl $16, %esp subl $4, %esp pushl $9 pushl $.LC2 strncpy(s1.id, ID, sizeof(ID)); # s1.age = AGE; # s2 = &s1; # printf("Name : %s %s\nID : %s\nAge : %i\n", # s2->first, s2->last, s2->id, s2 ->age); # clean up and exit addl $16, %esp subl $4, %esp pushl $9 pushl $.LC2 leal -72(%ebp), %eax addl $40, %eax pushl %eax call strncpy movl $19, -12(%ebp) movl %eax, -76(%ebp) subl $12, %esp movl -76(%ebp), %eax pushl 60(%eax) addl $20, %eax pushl -76(%ebp) pushl $.LC3 call printf addl $32, %esp movl $0, %eax leave ret
Problem 5: Answer int main ( int argc, char** argv ) { struct student s1; struct student *s2; strncpy ( s1.first, fName, sizeof ( fName ) ); strncpy ( s1.last , lName, sizeof ( lName ) ); strncpy ( s1.id , ID , sizeof ( ID ) ); s1.age = AGE; s2 = &s1; printf ( "Name : %s %s\nID : %s\nAge : %i\n", s2 -> first, s2 -> last, s2 -> id, s2 -> age ); return 0; }
Problem 6: Arrays of structs .LC0: .string "%i : %s - “ .LC1: .string "Has no partner\n“ .LC2: .string "Partnered with : %s \n“ .align 32 .LC3: .string "Claims parter: %s, but not mutual\n“ partner_check: pushl %ebp movl %esp,%ebp subl $20,%esp pushl %ebx nop movl $0,-4(%ebp) .p2align 4,,7 .L3: cmpl $5,-4(%ebp) jle .L6 jmp .L4 .L6: addl $-4,%esp movl -4(%ebp),%eax movl %eax,%ecx movl %ecx,%edx sall $4,%edx addl %eax,%edx #define MAX_STRING 20 #define MAX_STUDENTS 6 #struct student #{ # char first [ MAX_STRING ]; # char last [ MAX_STRING ]; # char id [ MAX_STRING ]; # int age; # struct student *partner; #}; # Lines with < symbols are moving # data for the printf command at # the end of the < block. left # in for informational purposes <
Problem 6: Arrays of structs leal 0(,%edx,4),%eax movl %eax,%edx addl 8(%ebp),%edx leal 40(%edx),%eax pushl %eax movl -4(%ebp),%eax pushl $.LC0 call printf addl $16,%esp movl %eax,%ecx movl %ecx,%edx sall $4,%edx addl %eax,%edx movl 8(%ebp),%edx cmpl $0,64(%edx,%eax) jne .L7 addl $-12,%esp pushl $.LC1 jmp .L5 .p2align 4,,7 < < printf ( "%i : %s - ", j, class[j].ID ); < printf ( "Has no partner\n" );
Problem 6: Arrays of structs movl -4(%ebp),%eax movl %eax,%ecx movl %ecx,%edx sall $4,%edx addl %eax,%edx leal 0(,%edx,4),%eax movl 8(%ebp),%edx movl 64(%edx,%eax),%eax movl -4(%ebp),%edx movl %edx,%ebx movl %ebx,%ecx sall $4,%ecx addl %edx,%ecx leal 0(,%ecx,4),%edx movl %edx,%ecx addl 8(%ebp),%ecx cmpl %ecx,64(%eax) jne .L9 addl $-8,%esp addl $40,%eax pushl %eax pushl $.LC2 call printf addl $16,%esp jmp .L5 .p2align 4,,7 < < printf ( "Partnered with : %s \n", < class[j].partner->ID );
Problem 6: Arrays of structs addl $-8,%esp movl -4(%ebp),%eax movl %eax,%ecx movl %ecx,%edx sall $4,%edx addl %eax,%edx leal 0(,%edx,4),%eax movl 8(%ebp),%edx movl 64(%edx,%eax),%eax addl $40,%eax pushl %eax pushl $.LC3 call printf addl $16,%esp .L10: .L8: .L5: incl -4(%ebp) jmp .L3 .p2align 4,,7 .L4: .L2: movl -24(%ebp),%ebx movl %ebp,%esp popl %ebp ret < < printf ( "Claims parter: %s, but not mutual\n", < class[j].partner->ID );
Problem 6: Answer void partner_check ( struct student * class ) { int j; for (j = 0; j < MAX_STUDENTS; j++ ) printf ( "%i : %s - ", j, class[j].ID ); if ( (class+j)->partner == NULL ) printf ( "Has no partner\n" ); else if ( (class+j)->partner->partner == (class+j) ) printf ( "Partnered with : %s \n", class[j].partner->ID ); else printf ( "Claims parter: %s, but not mutual\n", }