我们都知道数据x ,y 的值交换,可以用到c 指针来实现,
具体到汇编层面,是如何实现的呢。
请看下面的例子:
1、建立一个point.c 文件,来实现x 和y 值的交换。
vi point.c
#include <stdio.h> void change(int *x, int *y){ int z = *x; *x = *y; *y = z; } int main() { int x = 10; int y =20; change(&x, &y); printf("x=%d,y=%d \n", x, y); return 0; }
2、编译为.o 文件
#gcc -c point.c
3、汇编反编译成文本
#objdump -d point.o
point.o: file format elf64-x86-64 Disassembly of section .text: change 函数 0000000000000000 <change>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 48 89 7d e8 mov %rdi,-0x18(%rbp) x的地址 8: 48 89 75 e0 mov %rsi,-0x20(%rbp) y的地址 c: 48 8b 45 e8 mov -0x18(%rbp),%rax x的地址⇒%rax 10: 8b 00 mov (%rax),%eax z = *x 12: 89 45 fc mov %eax,-0x4(%rbp) z ⇒ -0x4(%rbp) 15: 48 8b 45 e0 mov -0x20(%rbp),%rax y的地址⇒%rax 19: 8b 10 mov (%rax),%edx y的值⇒%edx 1b: 48 8b 45 e8 mov -0x18(%rbp),%rax x的地址⇒%rax 1f: 89 10 mov %edx,(%rax) y的值(%edx) ⇒x *x = *y; 21: 48 8b 45 e0 mov -0x20(%rbp),%rax y的地址⇒%rax 25: 8b 55 fc mov -0x4(%rbp),%edx z的值(-0x4(%rbp)) ⇒%edx 28: 89 10 mov %edx,(%rax) z的值(%edx) ⇒y *y = z; 2a: c9 leaveq 2b: c3 retq main 函数 000000000000002c <main>: 2c: 55 push %rbp 2d: 48 89 e5 mov %rsp,%rbp 30: 48 83 ec 10 sub $0x10,%rsp 34: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp) int x = 10; 3b: c7 45 f8 14 00 00 00 movl $0x14,-0x8(%rbp) int y =20; 42: 48 8d 55 f8 lea -0x8(%rbp),%rdx y 的地址 ⇒%rdx 46: 48 8d 45 fc lea -0x4(%rbp),%rax x 的地址 ⇒%rax 4a: 48 89 d6 mov %rdx,%rsi y 的地址 ⇒%rsi (地址参数y) 4d: 48 89 c7 mov %rax,%rdi x 的地址 ⇒%rdi (地址参数x) 50: e8 00 00 00 00 callq 55 <main+0x29> 55: 8b 55 f8 mov -0x8(%rbp),%edx 58: 8b 4d fc mov -0x4(%rbp),%ecx 5b: b8 00 00 00 00 mov $0x0,%eax 60: 89 ce mov %ecx,%esi 62: 48 89 c7 mov %rax,%rdi 65: b8 00 00 00 00 mov $0x0,%eax 6a: e8 00 00 00 00 callq 6f <main+0x43> 6f: b8 00 00 00 00 mov $0x0,%eax 74: c9 leaveq 75: c3 retq
从以上例子可以看出,地址传递,是把变量的地址,作为参数传递过去了。
change 函数里面,直接把x,y 的地址中的值通过变量z 来进行了交换。
change 退出时没有参数返回,因为x,y 的地址(也就是main 中的 x,y 栈地址)中保存的值,已经发生了交换。