位运算交换和变量交换的汇编比较(讨论)
|
gis_ivy
侠客
|
[1楼]
大 中
小 发表于 2006-11-4 02:00:11 只看该作者
位运算交换和变量交换的汇编比较(讨论) 呵呵,一年多没有做过关于C的东西了,今天趁着兴起,多做点点,明天,继续c sharp..8-)
下面是传说中的不用变量交换两个值的例子,看看到底何方神圣 $ gcc -g test.c -o test YETIboy@ ~ $ gdb test GNU gdb 2003-09-20-cvs (cygwin-special) Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, welcome to change it and/or distribute copies of it under certai Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" f This GDB was configured as "i686-pc-cygwin"... (gdb) l 1 #include <stdlib.h> 2 void func(int *m, int *n) { 3 int temp; 4 temp = *m; 5 *m = *n; 6 *n = temp; 7 } 8 main() { 9 int a = 31, b = 123; 10 printf("Before exchanging:\ta = %d,b = %d \n", a, (gdb) 11 a = a ^ b; 12 b = b ^ a; 13 a = a ^ b; 14 printf("Exchange's done:\ta = %d,b = %d",a,b); 15 func(&a,&b); 16 printf("\nExchanged Again!\ta = %d,b = %d",a,b); 17 } (gdb) r Starting program: /home/YETIboy/test.exe Before exchanging: a = 31,b = 123 Exchange's done: a = 123,b = 31 Exchanged Again! a = 31,b = 123 Program exited with code 040. ※※※以上是运行结果的检验※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※ (gdb) disass main Dump of assembler code for function main: 0x00401110 <main+0>: push %ebp 0x00401111 <main+1>: mov %esp,%ebp 0x00401113 <main+3>: sub $0x18,%esp 在这里声请局部变量空间!!!! 0x00401116 <main+6>: and $0xfffffff0,%esp 0x00401119 <main+9>: mov $0x0,%eax 0x0040111e <main+14>: mov %eax,0xfffffff4(%ebp) 0x00401121 <main+17>: mov 0xfffffff4(%ebp),%eax 0x00401124 <main+20>: call 0x4014f0 <_alloca> 0x00401129 <main+25>: call 0x401580 <__main> ******进入main函数块****************************************** 0x0040112e <main+30>: movl $0x1f,0xfffffffc(%ebp) a = 31; 0x00401135 <main+37>: movl $0x7b,0xfffffff8(%ebp) b = 123; 0x0040113c <main+44>: mov 0xfffffff8(%ebp),%eax b的值放到eax中 0x0040113f <main+47>: mov %eax,0x8(%esp,1) 借助于eax把b的值传给printf参数表 0x00401143 <main+51>: mov 0xfffffffc(%ebp),%eax 把a的值放到eax中 0x00401146 <main+54>: mov %eax,0x4(%esp,1) 借助于eax把a的值传给printf参数表! 0x0040114a <main+58>: movl $0x401090,(%esp,1) 0x00401151 <main+65>: call 0x401590 <printf> 呼叫printf,c libarary runtime,传递a,b的值给printf 0x00401156 <main+70>: mov 0xfffffff8(%ebp),%edx 把b的值传给edx 0x00401159 <main+73>: lea 0xfffffffc(%ebp),%eax 把a的地址!!传给eax 0x0040115c <main+76>: xor %edx,(%eax) a = a^b 0x0040115e <main+78>: mov 0xfffffffc(%ebp),%edx 把a的值放到edx中 0x00401161 <main+81>: lea 0xfffffff8(%ebp),%eax 得到b的地址放到eax中 0x00401164 <main+84>: xor %edx,(%eax) b = b^a ---Type <return> to continue, or q <return> to quit--- 0x00401166 <main+86>: mov 0xfffffff8(%ebp),%edx 0x00401169 <main+89>: lea 0xfffffffc(%ebp),%eax 0x0040116c <main+92>: xor %edx,(%eax) a = a^b *********位运算共用9句指令完成交换**************************************** 0x0040116e <main+94>: mov 0xfffffff8(%ebp),%eax 0x00401171 <main+97>: mov %eax,0x8(%esp,1) 0x00401175 <main+101>: mov 0xfffffffc(%ebp),%eax 0x00401178 <main+104>: mov %eax,0x4(%esp,1) 0x0040117c <main+108>: movl $0x4010d0,(%esp,1) 0x00401183 <main+115>: call 0x401590 <printf> 再次接受a,b的值,调用printf 0x00401188 <main+120>: lea 0xfffffff8(%ebp),%eax 0x0040118b <main+123>: mov %eax,0x4(%esp,1) 0x0040118f <main+127>: lea 0xfffffffc(%ebp),%eax 0x00401192 <main+130>: mov %eax,(%esp,1) 0x00401195 <main+133>: call 0x401050 <func> 再次把a,b的值放入参数表,调用func 0x0040119a <main+138>: mov 0xfffffff8(%ebp),%eax 0x0040119d <main+141>: mov %eax,0x8(%esp,1) 0x004011a1 <main+145>: mov 0xfffffffc(%ebp),%eax 0x004011a4 <main+148>: mov %eax,0x4(%esp,1) 0x004011a8 <main+152>: movl $0x4010f0,(%esp,1) 0x004011af <main+159>: call 0x401590 <printf> 最后一次调用printf,同样接受参数a,b 0x004011b4 <main+164>: leave 释放堆栈帧 0x004011b5 <main+165>: ret 返回上级函数(就是调用main()的函数!它们是操作系统装载exe和退出程序时作的清理工作,类似于c++的构造函数和析构函数的功能) ※※※※※※※※※※※※※※※※※※※main()结束※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※ End of assembler dump. (gdb) disass func ※※※※※※※※※※※※※※※查看func的代码※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※ Dump of assembler code for function func: 0x00401050 <func+0>: push %ebp 0x00401051 <func+1>: mov %esp,%ebp 建立堆栈帧,用来函数返回 0x00401053 <func+3>: sub $0x4,%esp 声请一个变量地址(没有赋值!!) 0x00401056 <func+6>: mov 0x8(%ebp),%eax 把a的地址放到eax中 0x00401059 <func+9>: mov (%eax),%eax 取m的值到eax中 0x0040105b <func+11>: mov %eax,0xfffffffc(%ebp) temp = *m 0x0040105e <func+14>: mov 0x8(%ebp),%edx 把a的地址放到edx中 0x00401061 <func+17>: mov 0xc(%ebp),%eax 把b的地址放到eax中 0x00401064 <func+20>: mov (%eax),%eax 把b的值放到eax中 0x00401066 <func+22>: mov %eax,(%edx) *m = *n 0x00401068 <func+24>: mov 0xc(%ebp),%edx 把b的地址放到edx中 0x0040106b <func+27>: mov 0xfffffffc(%ebp),%eax temp的值放到eax中 0x0040106e <func+30>: mov %eax,(%edx) *n = temp; ***************共用10句完成交换,并且多了个变量空间************************ 0x00401070 <func+32>: leave 0x00401071 <func+33>: ret End of assembler dump. (gdb) 光从语句来判定,位运算胜利:) 下面我来试试谁到底更快 |
|
TOP |





