通过编写简单的for循环线性查找某一个元素,计算出前后的时间差,然后写一个同样功能的汇编版本,计算出时间差,我们看看两者在执行一百万次所执行的时间差
头文件:
extern "C" {
bool AsmFindArray(long n, long array[], long count);
bool FindArray(long n, long array[], long count);
}
我们使用extern C,让编译器按照C语言的规则编译产生目标函数。
入口函数:
// main.cpp - Testing FindArray and AsmFindArray
#include <iostream>
#include <time.h>
#include "findarr.h"
using namespace std;
int main(){
// Fill an array with pseudorandom integers.
const unsigned ARRAY_SIZE = 10000;
const unsigned LOOP_SIZE = 1000000;
long array[ARRAY_SIZE];
for(unsigned i = 0; i < ARRAY_SIZE; i++)
array[i] = rand();
long searchVal;
time_t startTime, endTime;
cout << "Enter a value to find: ";
cin >> searchVal;
cout << "Please wait. This will take between 10 and 30 seconds...\n";
// Test the C++ function
time(&startTime);
bool found = false;
for (int n = 0; n < LOOP_SIZE; n++)
found = FindArray(searchVal,array,ARRAY_SIZE);
time(&endTime);
cout << "Elapsed CPP time: " << long(endTime - startTime)
<< " seconds. Found = " << found << endl;
// Test the Assembly language procedure:
time(&startTime);
found = false;
for(n = 0; n < LOOP_SIZE; n++)
found = AsmFindArray(searchVal, array,ARRAY_SIZE);
time(&endTime);
cout << "Elapsed ASM time: " << long(endTime - startTime)
<< " seconds. Found = " << found << endl;
return 0;
}
FindArray的C++实现函数:
#include "findarr.h"
bool FindArray(long n, long array[], long count)
{
long *p = array;
for (int i = 0; i < count; i++,p++)
if (n == *p)
return true;
return false;
}
AsmFindArray的实现函数:
TITLE AsmFindArray Procedure (AsmFindArray.asm)
.586
.model flat,C
AsmFindArray PROTO,
srchVal:DWORD, arrayPtr:PTR DWORD, count:DWORD
.code
;----------------------------------------------------------------------
AsmFindArray PROC USES edi,
srchVal:DWORD, arrayPtr:PTR DWORD, count:DWORD
;
; Performs a linear search for a 32-bit integer
; in an array of integers. Returns a boolean
; value in AL indicating if the integer was found.
;----------------------------------------------------------------------
true = 1
false = 0
mov eax,srchVal ; search value
mov ecx,count ; number of items
mov edi,arrayPtr ; pointer to array
repne scasd ; do the search
jz returnTrue ; ZF = 1 if ound.
returnFalse:
mov al,false
jmp short exit
returnTrue:
mov al,true
exit:
ret
AsmFindArray ENDP
END
注意,C++链接汇编文件,在32位模式下必须指定Model为:.model flat,C. 在这里,我们使用了repne scasd命令替代循环的loop指令优化代码。编译器编译C++的FindArray函数默认是使用loop的。
我们使用ml /c 指令编译FindArray.cpp 产生FindArray.obj ,使用ml /c /coff AsmFindArray.asm 生成AsmFindArray.obj文件
然后用link main.obj FindArray.obj AsmFindArray.obj文件生成最后的main.exe
最后,我们看看结果的输出:
我们可以看出结果的差别还是很大的,这说明在某些特殊的场合,我们可以利用repne repe scasd scasb scasw等这些指令优化传统的for循环。