Bryand and O'Hallaron Chapter 3 Section 4.3 Pointer Example ------------------------------------------------------ colosus:~/bando/chap3/sec4>more exchange.c #include int exchange(int *xp, int y); main() { int a = 4; int b = exchange(&a, 3); printf("a = %d, b = %d\n", a, b); } int exchange(int *xp, int y) { int x = *xp; *xp = y; return x; } colosus:~/bando/chap3/sec4>gcc exchange.c colosus:~/bando/chap3/sec4>./a.out a = 3, b = 4 ------------------------------------------------------- colosus:~/bando/chap3/sec4>gcc -O2 -S exchange.c colosus:~/bando/chap3/sec4>more exchange.s .file "exchange.c" .text .p2align 4,,15 .globl exchange .type exchange, @function exchange: pushl %ebp # save old frame pointer movl %esp, %ebp # create new frame pointer ------------------------------------------------------------- movl 8(%ebp), %edx # get xp (an address) movl 12(%ebp), %ecx # get y movl (%edx), %eax # get x at *xp (and return x) movl %ecx, (%edx) # store y at *xp ------------------------------------------------------------- popl %ebp # restore old frame pointer ret # return value in %eax .size exchange, .-exchange .section .rodata.str1.1,"aMS",@progbits,1 .LC0: .string "a = %d, b = %d\n" .text .p2align 4,,15 .globl main .type main, @function main: leal 4(%esp), %ecx # save value of %esp (%esp+4) andl $-16, %esp # skip bytes so %esp = 0x???????0 pushl -4(%ecx) # push original value of %esp on stack pushl %ebp # save old frame pointer movl %esp, %ebp # create new frame pointer pushl %ecx # push original %esp+4 on stack subl $36, %esp # reserve 36 bytes on stack ------------------------------------------------------------------------ leal -8(%ebp), %eax # %eax = address where a is stored movl $4, -8(%ebp) # a = 4 movl $3, 4(%esp) # constant 3 on the stack movl %eax, (%esp) # address of a on the stack call exchange # return address on stack movl %eax, 8(%esp) # return value on stack movl -8(%ebp), %eax # value of a in %eax movl $.LC0, (%esp) # address of string on stack movl %eax, 4(%esp) # value of a on stack call printf ----------------------------------------------------------------------- addl $36, %esp # undo "reserve 36 bytes" popl %ecx # %ecx = original %esp+4 popl %ebp # restore old frame pointer leal -4(%ecx), %esp # restore original value of %esp ret .size main, .-main .ident "GCC: (GNU) 4.1.2 20070502 (Red Hat 4.1.2-12)" .section .note.GNU-stack,"",@progbits colosus:~/bando/chap3/sec4> ----------------------------------------------------------------------- When the call exchange instruction is executed, the stack contains memory (the stack) +-----------------+ +------>| |<------ 40(%esp) main's frame pointer, &ebp | +-----------------+ | | |<------ 36(%esp) | +-----------------+ | +-->| 0x00000004 |<------ 32(%esp) or -8(%ebp) | | +-----------------+ | | | |<------ 28(%esp) | | +-----------------+ | | | |<------ 24(%esp) | | +-----------------+ | | | |<------ 20(%esp) | | +-----------------+ | | | |<------ 16(%esp) | | +-----------------+ | | | |<------ 12(%esp) | | +-----------------+ | | | 0x00000003 |<------ 8(%esp) | | +-----------------+ | +---| xp = &a |<------ 4(%esp | +-----------------+ +-----------------+ | | return address |<------ | | %esp | +-----------------+ +-----------------+ +-------| old %ebp here |<------ -4(%esp) <--- new %ebp points here +-----------------+ | |<------ -8(%esp) +-----------------+ | |<------ -12(%esp) +-----------------+