CSE 351: Week 4 Tom Bergan, TA 1 Does this code look okay? int - - PowerPoint PPT Presentation

cse 351 week 4
SMART_READER_LITE
LIVE PREVIEW

CSE 351: Week 4 Tom Bergan, TA 1 Does this code look okay? int - - PowerPoint PPT Presentation

CSE 351: Week 4 Tom Bergan, TA 1 Does this code look okay? int binarySearch(int a[], int length, int key) { int low = 0; int high = length - 1; while (low <= high) { int mid = (low + high) / 2; int midVal = a[mid]; if (midVal < key)


slide-1
SLIDE 1

CSE 351: Week 4

Tom Bergan, TA

1

slide-2
SLIDE 2

2

int binarySearch(int a[], int length, int key) { int low = 0; int high = length - 1; while (low <= high) { int mid = (low + high) / 2; int midVal = a[mid]; if (midVal < key) low = mid + 1; else if (midVal > key) high = mid - 1; else return mid; // key found } return -1; // key not found }

Does this code look okay?

slide-3
SLIDE 3

Does this code look okay?

3

int binarySearch(int a[], int length, int key) { int low = 0; int high = length - 1; while (low <= high) { int mid = (low + high) / 2; int midVal = a[mid]; if (midVal < key) low = mid + 1; else if (midVal > key) high = mid - 1; else return mid; // key found } return -1; // key not found } int mid = (low + high) / 2;

What if length > 230?

slide-4
SLIDE 4

4

int mid = (low + high) / 2;

What if length > 230? ... then we could have: low = 230 = 0x40000000 high = 230+1 = 0x40000001 low + high = 231+1 = 0x80000001 Oops, in two’s complement, this is a negative number!

int midVal = a[mid];

Crashes because mid < 0 (low + high) / 2 = 0xC0000000 = -3221225472

Does this code look ok?

slide-5
SLIDE 5

5

int mid = (low + high) / 2;

How can we fix the bug?

int mid = low + ((high - low) / 2);

(There are other ways, but I think this is the simplest to understand)

slide-6
SLIDE 6

6

java.util.Arrays.binarySearch

This was an actual bug in Java

This bug went unnoticed for years. See: http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html Understanding binary number representations is important!

slide-7
SLIDE 7

Check your textbook:

Don’t use the international edition! The homework problems are different.

7

slide-8
SLIDE 8

Today

  • Questions on Hw 2 or Lab 2?
  • Procedure calls

8

slide-9
SLIDE 9

Procedure Call Example

9

int sum(int x, int y) { return x + y; }

Callee

int z = sum(1, 2);

Caller

slide-10
SLIDE 10

Procedure Call Example

(IA32/Linux)

10

int z = sum(1, 2);

Caller 0x8001 pushl $2 0x8005 pushl $1 0x8009 call sum 0x8013 addl $8, %esp Caller in assembly

*note: these instruction addresses are completely made up for this example

The Stack : :

%esp

slide-11
SLIDE 11

Procedure Call Example

(IA32/Linux)

11

int z = sum(1, 2);

Caller 0x8001 pushl $2 0x8005 pushl $1 0x8009 call sum 0x8013 addl $8, %esp Caller in assembly

*note: these instruction addresses are completely made up for this example

The Stack 2 : :

%esp

slide-12
SLIDE 12

Procedure Call Example

(IA32/Linux)

12

int z = sum(1, 2);

Caller 0x8001 pushl $2 0x8005 pushl $1 0x8009 call sum 0x8013 addl $8, %esp Caller in assembly

*note: these instruction addresses are completely made up for this example

The Stack 2 1 : :

%esp

slide-13
SLIDE 13

Procedure Call Example

(IA32/Linux)

13

int z = sum(1, 2);

Caller 0x8001 pushl $2 0x8005 pushl $1 0x8009 call sum 0x8013 addl $8, %esp Caller in assembly

*note: these instruction addresses are completely made up for this example

The Stack 2 1 0x8013 : :

%esp

slide-14
SLIDE 14

Procedure Call Example

(IA32/Linux)

14

movl 8(%esp), %edi movl 4(%esp), %eax addl %edi, %eax ret

Callee in assembly (simple version) The Stack 2 1 0x8013 : :

4(%esp)

int sum(int x, int y) { return x + y; }

Callee

8(%esp) %esp

x y Registers

%edi

2

slide-15
SLIDE 15

Procedure Call Example

(IA32/Linux)

15

Callee in assembly (simple version) The Stack 2 1 0x8013 : :

4(%esp)

int sum(int x, int y) { return x + y; }

Callee

8(%esp) %esp

x y Registers

%eax

2 1

movl 8(%esp), %edi movl 4(%esp), %eax addl %edi, %eax ret

%edi

slide-16
SLIDE 16

Procedure Call Example

(IA32/Linux)

16

Callee in assembly (simple version) The Stack 2 1 0x8013 : :

4(%esp)

int sum(int x, int y) { return x + y; }

Callee

8(%esp) %esp

%eax has the return value!

x y Registers

%eax

2 3

movl 8(%esp), %edi movl 4(%esp), %eax addl %edi, %eax ret

%edi

slide-17
SLIDE 17

Procedure Call Example

(IA32/Linux)

17

Callee in assembly (simple version) The Stack 2 1 : :

int sum(int x, int y) { return x + y; }

Callee

%esp

%eax has the return value!

x y Registers

%eip %eax

2 3 0x8013 0x8013

movl 8(%esp), %edi movl 4(%esp), %eax addl %edi, %eax ret

%edi

slide-18
SLIDE 18

Procedure Call Example

(IA32/Linux)

18

int z = sum(1, 2);

Caller 0x8001 pushl $2 0x8005 pushl $1 0x8009 call sum 0x8013 addl $8, %esp Caller in assembly

*note: these instruction addresses are completely made up for this example

The Stack 2 1 : : Registers

%eip %eax

2 3 0x8013

%esp %edi

slide-19
SLIDE 19

Procedure Call Example

(IA32/Linux)

19

int z = sum(1, 2);

Caller 0x8001 pushl $2 0x8005 pushl $1 0x8009 call sum 0x8013 addl $8, %esp Caller in assembly

*note: these instruction addresses are completely made up for this example

The Stack 2 1 : : Registers

%eip %eax

2 3 0x8013

%esp %edi

slide-20
SLIDE 20

Procedure Call Example

(IA32/Linux)

20

int z = sum(1, 2);

Caller 0x8001 pushl $2 0x8005 pushl $1 0x8009 call sum 0x8013 addl $8, %esp Caller in assembly

*note: these instruction addresses are completely made up for this example

Problem:

  • What if Caller used %edi

before making the call?

Registers

%eip %edi %eax

2 3 0x8013

slide-21
SLIDE 21

Procedure Call Example

(IA32/Linux)

21

int d = 5; int z = sum(1, 2);

Caller 0x7fff movl $5, %edi 0x8001 pushl $2 0x8005 pushl $1 0x8009 call sum 0x8013 addl $8, %esp Caller in assembly

*note: these instruction addresses are completely made up for this example

Problem:

  • What if Caller used %edi

before making the call?

Registers

%eip %eax

2 3 0x8013

sum() overwrote %edi! Need to save ...

%edi

slide-22
SLIDE 22

Saving Registers

  • Some are caller save
  • IA32: %eax, %edx, %ecx
  • These are very commonly used

(caller should expect they will be clobbered)

  • Some are callee save
  • IA32: %ebx, %edi, %esi
  • These are less commonly used

22

from prior example

slide-23
SLIDE 23

Procedure Call Example

(IA32/Linux)

23

Callee in assembly (better version) The Stack 2 1 0x8013 : :

int sum(int x, int y) { return x + y; }

Callee

%esp

x y

setup body cleanup

%ebp

pushl %ebp movl %esp, %ebp pushl %edi movl 12(%ebp), %edi movl 8(%ebp), %eax addl %edi, %eax movl (%esp), %edi movl %ebp, %esp popl %ebp ret

slide-24
SLIDE 24

Procedure Call Example

(IA32/Linux)

24

The Stack 2 1 0x8013 : :

int sum(int x, int y) { return x + y; }

Callee

%esp

x y

setup body cleanup

  • ld %ebp

%ebp

Callee in assembly (better version)

pushl %ebp movl %esp, %ebp pushl %edi movl 12(%ebp), %edi movl 8(%ebp), %eax addl %edi, %eax movl (%esp), %edi movl %ebp, %esp popl %ebp ret

slide-25
SLIDE 25

Procedure Call Example

(IA32/Linux)

25

The Stack 2 1 0x8013 : :

int sum(int x, int y) { return x + y; }

Callee

%esp

x y

setup body cleanup

  • ld %ebp

%ebp

Callee in assembly (better version)

pushl %ebp movl %esp, %ebp pushl %edi movl 12(%ebp), %edi movl 8(%ebp), %eax addl %edi, %eax movl (%esp), %edi movl %ebp, %esp popl %ebp ret

slide-26
SLIDE 26

Procedure Call Example

(IA32/Linux)

26

The Stack 2 1 0x8013 : :

int sum(int x, int y) { return x + y; }

Callee

%esp

x y

setup body cleanup

  • ld %ebp

%ebp

  • ld %edi

saved %edi

Callee in assembly (better version)

pushl %ebp movl %esp, %ebp pushl %edi movl 12(%ebp), %edi movl 8(%ebp), %eax addl %edi, %eax movl (%esp), %edi movl %ebp, %esp popl %ebp ret

slide-27
SLIDE 27

Procedure Call Example

(IA32/Linux)

27

The Stack 2 1 0x8013 : :

int sum(int x, int y) { return x + y; }

Callee

%esp

x y

setup body cleanup

%ebp 8(%ebp) 12(%ebp)

Key: %ebp is fixed for the entire function

  • ld %ebp
  • ld %edi

Callee in assembly (better version)

pushl %ebp movl %esp, %ebp pushl %edi movl 12(%ebp), %edi movl 8(%ebp), %eax addl %edi, %eax movl (%esp), %edi movl %ebp, %esp popl %ebp ret

slide-28
SLIDE 28

Procedure Call Example

(IA32/Linux)

28

The Stack 2 1 0x8013 : :

int sum(int x, int y) { return x + y; }

Callee

%esp

x y

setup body cleanup

%ebp

  • ld %ebp
  • ld %edi

restoring %edi

8(%ebp) 12(%ebp)

Callee in assembly (better version)

pushl %ebp movl %esp, %ebp pushl %edi movl 12(%ebp), %edi movl 8(%ebp), %eax addl %edi, %eax movl (%esp), %edi movl %ebp, %esp popl %ebp ret

slide-29
SLIDE 29

Procedure Call Example

(IA32/Linux)

29

The Stack 2 1 0x8013 : :

int sum(int x, int y) { return x + y; }

Callee

%esp

x y

setup body cleanup

%ebp

  • ld %ebp
  • ld %edi

restoring %ebp

Callee in assembly (better version)

pushl %ebp movl %esp, %ebp pushl %edi movl 12(%ebp), %edi movl 8(%ebp), %eax addl %edi, %eax movl (%esp), %edi movl %ebp, %esp popl %ebp ret

slide-30
SLIDE 30

Why use a frame pointer?

(%ebp)

30

To make debugging easier

  • %esp may move
  • %ebp is fixed

int sum(int x, int y) { return x + y; }

Callee Your compiler emits a symbol map

y → 12(%ebp) x → 8(%ebp)

The Stack 2 1 0x8013 : :

%esp

x y

%ebp

  • ld %ebp
  • ld %edi

8(%ebp) 12(%ebp)

gdb uses this map when you write

print x

slide-31
SLIDE 31

Aside: how does gdb’s “backtrace” work?

31

Follow return addresses!

  • use old %ebp to find prior frame

The Stack 2 1 0x8013 : :

%esp

x y

%ebp

  • ld %ebp
  • ld %edi

8(%ebp) 12(%ebp)

Pseudocode:

while (pc is not in “main”) { pc = 4(%ebp) %ebp = (%ebp) }

4(%ebp)

slide-32
SLIDE 32

How is x86-64 different?

  • Pass the first six arguments in registers
  • In this order: %rdi,%rsi,%rdx,%rcx,%r8,%r9
  • New register save convention
  • Callee save: %rbx,%rbp,%r12,%r13,%r14,%r15
  • Others are caller save
  • By default, gcc omits the frame pointer
  • It has to emit more complex debug info

(e.g., the location of argument x relative to %esp can change)

32

slide-33
SLIDE 33

Procedure Call Example

(x86-64/Linux)

33

addl %esi, %edi movl %edi, %eax ret

Callee in assembly

int sum(int x, int y) { return x + y; }

Callee

int z = sum(1, 2);

Caller movl $1, %edi movl $2, %esi call sum Caller in assembly

edi not rdi because int is 32-bits x86-64 with gcc does not use a frame pointer

Tip: you can force gcc to emit code with a frame pointer using

gcc -fno-omit-frame-pointer