现在查看的简短程序实现如下操作:读取一个文件,对其进行加密,再将其输出到另一个文件。函数 TranslateBuffer 用一个 __asm 块定义语句,在一个字符数组内进行循环,并把每个字符与预定义值进行 XOR 运算。
内嵌语言可以使用函数形参、局部变量和代码标号。由于本例是由 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++ 启动程序从命令行读取输入和输出文件名。在循环内调用 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:
头文件 translat.h 包含了 TranslateBuffer 的一个函数原型:
如果在调试器调试程序时查看 Disassembly 窗口,那么,看到函数调用和返回究竟有多少开销是很有趣的。下面的语句将三个实参送入堆栈,并调用 TranslateBuffer。在 Visual C++ 的 Disassembly 窗口,激活 Show Source Code 和 Show Symbol Names 选项:
下面的代码对 TranslateBuffer 进行反汇编。编译器自动插入了一些语句用于设置 EBP,以及保存标准寄存器集合,集合内的寄存器不论是否真的会被过程修改,总是被保存。
- 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 选项,则将参数送入寄存器的三条语句如下:
编译器按要求生成 Debug 目标代码,这是非优化代码,适合于交互式调试。如果选择 Release 目标代码,那么编译器生成的代码就会更加有效(但易读性更差)。
本节前面给出的 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);
- }