C语言/C++内嵌汇编代码实例:文件加密
现在查看的简短程序实现如下操作:读取一个文件,对其进行加密,再将其输出到另一个文件。函数 TranslateBuffer 用一个 __asm 块定义语句,在一个字符数组内进行循环,并把每个字符与预定义值进行 XOR 运算。
内嵌语言可以使用函数形参、局部变量和代码标号。由于本例是由 Microsoft Visual C++ 编译的 Win32 控制台应用,因此其无符号整数类型为 32 位:
如果函数被调用几千次,那么其执行时间就比较可观了。为了消除这种开销,把内嵌代码插入调用 TranslateBuffer 的循环,得到更为有效的程序:
内嵌语言可以使用函数形参、局部变量和代码标号。由于本例是由 Microsoft Visual C++ 编译的 Win32 控制台应用,因此其无符号整数类型为 32 位:
void TranslateBuffer(char * buf, unsigned count, unsigned char eChar) { __asm { mov esi, buf mov ecx, count mov al, eChar L1: xor [esi],al inc esi loop L1 } // asm }
C++ 模块
C++ 启动程序从命令行读取输入和输出文件名。在循环内调用 TranslateBuffer 从文件读取数据块,加密,再将转换后的缓冲区写入新文件:// ENCODE.CPP 复制并加密文件。 #include <iostream> #include <fstream> #include "translat.h" using namespace std; int main( int argcount, char * args[] ) { // 从命令行读取输入和输出文件 if( argcount < 3 ) { cout << "Usage: encode infile outfile" << endl; return -1; } const int BUFSIZE = 2000; char buffer[BUFSIZE]; unsigned int count; // 字符计算 unsigned char encryptCode; cout << "Encryption code [0-255]? "; cin >> encryptCode; ifstream infile( args[1], ios::binary ); ofstream outfile( args[2], ios::binary ); cout << "Reading " << args[1] << " and creating " << args[2] << endl; while (!infile.eof() ) { infile.read(buffer, BUFSIZE ); count = infile.gcount(); TranslateBuffer(buffer, count, encryptCode); outfile.write(buffer, count); } return 0; }用命令提示符运行该程序,并传递输入和输岀文件名是最容易的。比如,下面的命令行读取 infile.txt,生成 encoded.txt:
encode infile.txt encoded.txt
头文件
头文件 translat.h 包含了 TranslateBuffer 的一个函数原型:void TranslateBuffer(char * buf, unsigned count, unsigned char eChar);
过程调用的开销
如果在调试器调试程序时查看 Disassembly 窗口,那么,看到函数调用和返回究竟有多少开销是很有趣的。下面的语句将三个实参送入堆栈,并调用 TranslateBuffer。在 Visual C++ 的 Disassembly 窗口,激活 Show Source Code 和 Show Symbol Names 选项:
; TranslateBuffer(buffer, count, encryptCode)
mov al,byte ptr [encryptCode]
push eax
mov ecx,dword ptr [count]
push ecx
lea edx,[buffer]
push edx
call TranslateBuffer (4159BFh)
add esp, 0Ch
push ebp mov ebp, esp sub esp,40h push ebx push esi push edi ;内嵌代码从这里开始。 mov esi,dword ptr [buf] mov ecx,dword ptr [count] mov al,byte ptr [eChar] L1: xor byte ptr [esi],al inc esi loop L1 (41D762h) ;内嵌代码结束。 pop edi pop esi pop ebx mov esp,ebp pop ebp ret若关闭了调试器 Disassembly 窗口的 Display Symbol Names 选项,则将参数送入寄存器的三条语句如下:
mov esi,dword ptr [ebp+8]
mov ecx,dword ptr [ebp+0Ch]
mov al,byte ptr [ebp+10h]
忽略过程调用
本节前面给出的 TranslateBuffer 中有 6 条内嵌指令,其执行总共需要 8 条指令。如果函数被调用几千次,那么其执行时间就比较可观了。为了消除这种开销,把内嵌代码插入调用 TranslateBuffer 的循环,得到更为有效的程序:
while (!infile.eof() ) { infile.read(buffer, BUFSIZE ); count = infile.gcount(); __asm { lea esi,buffer mov ecx,count mov al, encryptCode L1: xor [esi],al inc esi Loop L1 } // asm outfile.write(buffer, count); }