高手请进,关于C与汇编效率的讨论

/*
有以下5种方法实现两个整数的交换

swap,swap0, swap1用汇编语言编写
swap2, swap3用C语言编写

swap用中间变量方式实现

swap0用xchg指令实现

swap1用xor方法实现

swap2也是用xor方法实现

swap3用中间变量方法实现

问题:目的是测一测不同的swap函数的执行效率,看看C和汇编、不同算法之间的差别,分别计了一下时间,本以为使用xchg指令时间应该最短,但是结果却是xchg时间最长,而用c语言写的程序时间却最短。查看反汇编,C语言写的swap函数指令并不比汇编swap指令少,执行上用时却最少,很让人费解。

更费解的是,调整一下函数的声明顺序,执行时间上也不尽相同。
请高手给一个合理解释,最好有对应的测试代码,证明这个情况到底源于哪里呢??

*/
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "time.h"

void swap(int *x, int *y)
{
_asm
{
mov ecx, x
mov edx, y
mov eax, [ecx]
mov ebx, [edx]
mov [ecx], ebx
mov [edx], eax
}
}

void swap0(int *x, int *y)
{

_asm
{
mov ecx, x
mov edx, y
mov eax, [ecx]
xchg eax, [edx]
xchg eax, [ecx]
}

}

void swap1(int *x, int *y)
{
_asm
{
mov ecx, x
mov edx, y
mov eax, [ecx]
xor eax, [edx]
mov ebx, eax
xor ebx, [edx]
mov [edx], ebx
xor eax, ebx
mov [ecx], eax
}
}

void swap2 (int *x, int *y)
{
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}

void swap3 (int *x, int *y)
{
register z;
z = *x;
*x = *y;
*y = z;
}

int main(void)
{
int z1 = 3, z2 = 4;
int i;
int c = 50000000;
clock_t x;

x = clock();
for (i = 0; i < c; i++)
swap0(&z1, &z2);
printf("t0 = %d\t asm xchg\n", clock() - x);

x = clock();
for (i = 0; i < c; i++)
swap1(&z1, &z2);
printf("t1 = %d\t asm xor\n", clock() - x);

x = clock();
for (i = 0; i < c; i++)
swap2(&z1, &z2);
printf("t2 = %d\t c xor\n", clock() - x);

x = clock();
for (i = 0; i < c; i++)
swap3(&z1, &z2);
printf("t3 = %d\t c temp\n", clock() - x);

x = clock();
for (i = 0; i < c; i++)
swap(&z1, &z2);
printf("t = %d\t asm temp\n", clock() - x);

getchar();
return 0;
}

比较两次结果

这是完全相同的程序和配置多次运行的差异,再看下面这个

这是去掉了优化配置后的运行结果。


前两个的差异和不稳定性,是多线程系统下任务分配造成的。第三个,说明工程配置和编译环境的干扰非常大。


本身来说,现在的编程环境下,各种优化各种兼容,造成了C编译器编译的程序,汇编和C语言进行相同的操作没有本质差别(只有优化差别),无法通过这个方式进行汇编和C的效率比较。


如果要比较,那么安装一个纯UNIX吧(这个下面还可以获取微妙级时间片),通过纯汇编程序和纯C程序进行比较,才能看到差别。


总结:当前C编译器下,汇编和C代码运算几乎没有差异,而xchg,我认为是编译器没有相关优化造成的结果。

温馨提示:内容为网友见解,仅供参考
第1个回答  2013-09-27
目的是测一测不同的swap函数的执行效率,看看C和汇编、不同算法之间的差别,分别计了一下时间,本以为使用xchg指令时间应该最短,但是结果却是xchg时间最长,
--------------------------------------------------
xchg 是一个原子操作指令,会锁住内存总线,因此,会极大的降低效率,使得cpu流水线之类无法产生效果。xchg这个指令,优点是原子操作,缺点是效率低,当然时间最长。详细参见intel指令手册。

而用c语言写的程序时间却最短。查看反汇编,C语言写的swap函数指令并不比汇编swap指令少,执行上用时却最少,很让人费解。
------------------------------------------------
你的汇编指令编写的swap程序,无论是用到xchg,还是普通的中间变量,都是一些中规中矩的汇编过程。编译器无法优化。因为你已经是汇编程序了。而C语言写的交换程序,编译器会进行优化,编译器的开发者极其精通底层硬件体系结构。利用了一些底层硬件,你不知道的特性,比如流水线,cache等功能,效率当然大大提高。你不知道而已。

更费解的是,调整一下函数的声明顺序,执行时间上也不尽相同。
-------------------------------------------------------
具体是哪个函数。追问

就是调整了一下函数声明的顺序,比如把swap3放在最开始,似乎是最先声明的函数,执行时间上会慢下来,不知何故。
另外,能否简要举例说明一下C是怎么被优化成适合硬件特性的,谢谢

追答

可能是缓存cache问题吧。

刚开始没有任何缓存,所以速度慢。

比如第一个函数,没有cache,执行它的时候,把包含它的程序从磁盘读到内存。但是显然,一次性读取的大小,并不只是第一个函数,比如一次读取4k,显然会把后面几个函数全部读入。

所以,第二个第三个在读取第一个的时候一起读入了。所以就快了。

你可以,写几个无聊的函数,放在这些函数前面。那么这些swap函数就是平等的了。

比如无聊的函数可以这样写

void swap_wuliao1(int *x, int *y)
{
_asm
{
mov ecx, x
mov edx, y
mov eax, [ecx]
mov ebx, [edx]
mov [ecx], ebx
mov [edx], eax
}
}

void swap_wuliao2 (int *x, int *y)
{
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}

这2个函数和后面真的使用的函数式一样的,仅仅名称不一样。

把这2个函数放在最前面执行。作为warm up函数。

本回答被提问者采纳
第2个回答  2013-09-27
使用客户方

高手请进,关于C与汇编效率的讨论
本身来说,现在的编程环境下,各种优化各种兼容,造成了C编译器编译的程序,汇编和C语言进行相同的操作没有本质差别(只有优化差别),无法通过这个方式进行汇编和C的效率比较。如果要比较,那么安装一个纯UNIX吧(这个下面还可以获取微妙级时间片),通过纯汇编程序和纯C程序进行比较,才能看到差别。总结:...

关于汇编PUSH指令的 高手请进
这是进栈指令,栈的特点是先进后出(和队列相反),像上面,如果是两个的,但先进先出的话,出来的这个就是后进的那个了

c语言高手请进 编译结果太多该如何输出
这叫运行结果,不叫编译。你可以在源码中加入文件操作,把它输出到文件中。或者先编译好程序,然后在命令提示符中运行,使用重定向输出结果到文件中。例如你的文件名是test.exe,可以在命令提示符中先切换到你的exe所在路径,然后输入test.exe > 1.txt,这样结果就会被输出到文件1.txt中。

C\/C++高手请进 我有问题哈
1.我是做音频信号处理的。感觉matlab编程比较重要,C++次之。其实最重要的是数学。实际上咱们都是做数字信号处理的,无论是声音还是视频,都是二进制信号嘛。2.VC6是就是C++编译环境,Visual C++ 的简称 不过可以尝试VS2010,VC问题比较多。3.自学C++可以先看谭浩强的教程,十分简洁,十分快速入门。然...

c高手请进,我一个礼拜都没解决!求救!!
(1)C中最后不要用goto语句,很容易出问题;(2)为什么要转换成浮点数呢,换成整数就可以了 (3)代码太不规范,也太多了,根据你的要求,根本用不了这么复杂,我自己写了个,你自己看看吧 include<stdio.h> include<string.h> void main(){ int i,len,sum,n;char str[100];while(1){ ...

关于汇编偏移量的一些问题 高手请进
4、这里面于是就对应了段寄存器和偏移寄存器的概念。5、“一次只能寻16个字节”的意思是,一个地址可以存放一个字节的数据,偏移地址是4位,所以只能寻址2的4次方的地址,最终导致一次只能跨越寻16个字节的地址。6、这种说法是基于内存的角度,而不是基于CPU的角度,特别容易导致初学者混淆。

有请懂汇编的高手
也就是说shl byte ptr [edx], F0 这是一条汇编指令。其实它目前就存储在机器的 00005C50位置。存储的内容就是 C022F0.你用W32Dasm打开后和上面是一样的,只不过这次按照8字节排序,把他们连续到一起了。你按照第一个图形中的第二排。从上往下排列,就是C0 22 F0 -- 16 -- AD -- 62 ...

关于C语言的一个问题,高手请进
好吧,我来回答吧,其实是不需要的,我还特意测试了一下,编译成功而且调用过程都没有问题 解释一下,a.c文件中调用了b()函数,a.c包含了b.h头文件,所以a.c文件能正常调用b()函数,这点大家应该都没有问题,但main()中通过调用a()来间接调用b()函数需不需要b()的头文件呢,答案是不需要...

高手请进,问汇编语言程序设计问题
分类: 电脑\/网络 >> 程序设计 >> 其他编程语言 问题描述:31. MOV DL,AL NOT DL TEST DL,04H JE NEXT ┇ NEXT:…若上述程序段执行时产生分支,说明AL中的数第几位一定为1?程序段执行后CF是多少?32.DA1 DB‘ABCDEFGHI’DA2 DB 9 DUP(0)┇ LEA SI,DA1 LEA DI,DA2 MOV CX,...

高手请进关于热效率的问题
请问一下热效率的含义是什么其公式怎么求??... 请问一下热效率的含义是什么其公式怎么求?? 展开  我来答 分享 微信扫一扫 新浪微博 QQ空间 举报 浏览760 次 可选中1个或多个下面的关键词,搜索相关资料。也可直接点“搜索资料”搜索整个问题。 热效率 高手请进 搜索资料 本地图片 图片链接 提交回答...

相似回答