文章目录
- x86 REP指令内联汇编演示
- REP指令简介
- 演示1:REP STOS - 填充内存块
- 示例1:用字节填充内存
- 示例2:用双字填充内存
- 演示2:REP MOVS - 复制内存块
- 示例3:复制字符串
- 示例4:高效复制数组
- 演示3:REP CMPS - 比较内存块
- 示例5:比较两个字符串
- 演示4:REP SCAS - 搜索特定值
- 示例6:在字符串中搜索字符
- 演示5:REP前缀变体
- 示例7:REPE/REPNE 使用
- 演示6:实际应用 - 快速内存操作
- 示例8:高效内存清零
- 关键要点总结
x86 REP指令内联汇编演示
REP指令简介
REP(Repeat)是x86汇编中的字符串操作前缀指令,它重复执行后面的字符串操作指令(如MOVS、STOS、CMPS等),重复次数由ECX寄存器指定。
演示1:REP STOS - 填充内存块
示例1:用字节填充内存
#include<iostream>usingnamespacestd;intmain(){charbuffer1[100]={0};_asm{lea edi,buffer1;EDI指向缓冲区 mov al,0x41;填充字符'A'(ASCII0x41)mov ecx,50;填充50个字节 cld;清除方向标志(正向移动) rep stosb;重复执行STOSB}cout<<"填充后buffer1前50个字节: ";for(inti=0;i<50;i++){cout<<buffer1[i];}cout<<endl;return0;}示例2:用双字填充内存
#include<iostream>usingnamespacestd;intmain(){intbuffer2[100]={0};_asm{lea edi,buffer2;EDI指向缓冲区 mov eax,0x12345678;填充模式 mov ecx,25;填充25个双字(100字节) cld;清除方向标志 rep stosd;重复执行STOSD}cout<<"填充后buffer2前5个元素: ";for(inti=0;i<5;i++){cout<<hex<<buffer2[i]<<" ";}cout<<endl;return0;}演示2:REP MOVS - 复制内存块
示例3:复制字符串
#include<iostream>usingnamespacestd;intmain(){charsource[100]="Hello, x86 Assembly REP MOVS instruction!";chardest[100]={0};cout<<"复制前: source = "<<source<<endl;cout<<"复制前: dest = "<<dest<<endl;_asm{lea esi,source;ESI指向源 lea edi,dest;EDI指向目标 mov ecx,sizeof(source);要复制的字节数 cld;正向复制 rep movsb;重复字节复制}cout<<"复制后: dest = "<<dest<<endl;return0;}示例4:高效复制数组
#include<iostream>#include<iomanip>usingnamespacestd;intmain(){intsrcArray[10]={1,2,3,4,5,6,7,8,9,10};intdstArray[10]={0};cout<<"复制前dstArray: ";for(inti=0;i<5;i++){cout<<dstArray[i]<<" ";}cout<<"...";cout<<endl;_asm{lea esi,srcArray;源数组地址 lea edi,dstArray;目标数组地址 mov ecx,10;复制10个双字 cld;正向复制 rep movsd;重复双字复制(更高效)}cout<<"复制后dstArray: ";for(inti=0;i<10;i++){cout<<dstArray[i]<<" ";}cout<<endl;return0;}演示3:REP CMPS - 比较内存块
示例5:比较两个字符串
#include<iostream>usingnamespacestd;intmain(){charstr1[]="Hello World";charstr2[]="Hello World";charstr3[]="Hello Assembly";cout<<"比较 str1 和 str2: ";_asm{lea esi,str1 lea edi,str2 mov ecx,sizeof(str1);比较的字节数 cld repe cmpsb;重复比较,直到不相等或ECX=0;检查比较结果 je equal jmp not_equal equal:cout<<"字符串相等"<<endl;jmp done1 not_equal:cout<<"字符串不相等"<<endl;done1:}cout<<"比较 str1 和 str3: ";_asm{lea esi,str1 lea edi,str3 mov ecx,sizeof(str1);比较的字节数 cld repe cmpsb;重复比较,直到不相等或ECX=0je equal2 jmp not_equal2 equal2:cout<<"字符串相等"<<endl;jmp done2 not_equal2:cout<<"字符串不相等"<<endl;done2:}return0;}演示4:REP SCAS - 搜索特定值
示例6:在字符串中搜索字符
#include<iostream>usingnamespacestd;intmain(){chartext[]="Search for character 'x' in this text.";chartarget='x';cout<<"在文本中搜索字符 '"<<target<<"'"<<endl;cout<<"文本: "<<text<<endl;_asm{lea edi,text;EDI指向文本 mov al,target;要搜索的字符 mov ecx,sizeof(text);搜索长度 cld repne scasb;重复搜索直到找到或ECX=0;检查是否找到 jnz not_found;找到:计算位置 mov eax,sizeof(text)sub eax,ecx;位置=总长度-剩余ECX dec eax;调整(SCASB在找到后已递增EDI) cout<<"找到字符,位置: "<<eax<<endl;jmp done not_found:cout<<"未找到字符"<<endl;done:}return0;}演示5:REP前缀变体
示例7:REPE/REPNE 使用
#include<iostream>usingnamespacestd;intmain(){// REPE (REP while Equal) = REPZ (REP while Zero)// REPNE (REP while Not Equal) = REPNZ (REP while Not Zero)charpattern[]="ABCDABCDABCD";charsearch[]="ABCD";intpattern_len=12;intsearch_len=4;cout<<"在pattern中搜索search字符串"<<endl;_asm{mov ecx,pattern_len;最大搜索次数 sub ecx,search_len;调整搜索次数 inc ecx lea esi,pattern;主文本 lea edi,search;搜索模式 search_loop:push esi push edi push ecx mov ecx,search_len;比较的长度 cld repe cmpsb;比较直到不相等 pop ecx pop edi pop esi je found;如果全部相等则找到 inc esi;移动到下一个位置 loop search_loop;继续搜索 jmp not_found found:cout<<"找到模式,起始位置: "<<(esi-offset pattern)<<endl;jmp done not_found:cout<<"未找到模式"<<endl;done:}return0;}演示6:实际应用 - 快速内存操作
示例8:高效内存清零
#include<iostream>#include<chrono>usingnamespacestd;usingnamespacechrono;#defineSIZE1000000intmain(){char*largeBuffer=newchar[SIZE];// 方法1:使用C++循环autostart1=high_resolution_clock::now();for(inti=0;i<SIZE;i++){largeBuffer[i]=0;}autoend1=high_resolution_clock::now();// 方法2:使用REP STOSBautostart2=high_resolution_clock::now();_asm{mov edi,largeBuffer;EDI指向缓冲区xoreax,eax;AL=0mov ecx,SIZE;大小 cld rep stosb;快速填充0}autoend2=high_resolution_clock::now();autoduration1=duration_cast<microseconds>(end1-start1);autoduration2=duration_cast<microseconds>(end2-start2);cout<<"C++循环清零时间: "<<duration1.count()<<" 微秒"<<endl;cout<<"REP STOSB清零时间: "<<duration2.count()<<" 微秒"<<endl;delete[]largeBuffer;return0;}关键要点总结
- REP指令前缀:必须与字符串操作指令一起使用
- 计数器:ECX寄存器指定重复次数
- 方向标志:DF标志决定指针递增(CLD)或递减(STD)
- 常用组合:
REP MOVSB/MOVSW/MOVSD- 复制内存REP STOSB/STOSW/STOSD- 填充内存REP CMPSB/CMPSW/CMPSD- 比较内存REP SCASB/SCASW/SCASD- 搜索内存
- 变体:
REPE/REPZ- 相等时重复REPNE/REPNZ- 不相等时重复
- 性能:通常比手动循环更快,因为经过优化
这些演示展示了REP指令在内存操作中的强大功能和高效性,特别适合处理大量数据的场景。