汇编实战:用REPNZ SCASB与REPZ CMPSB从零实现strcmpA/W
本文介绍了使用纯汇编实现字符串比较函数strcmpA和strcmpW的方法。strcmpA通过repnz scasb计算字符串长度,repz cmpsb比较字符,并将结果存入EAX返回。strcmpW针对宽字符实现,使用repnz scasw和repz cmpsw指令处理双字节字符。两种实现都使用__declspec(naked)声明确保函数体完全由汇编指令构成,并正确处理堆栈平衡和参数传递。文中
目录
尽管C库提供了strcmp,但了解其最高效的硬件实现是深入系统编程的关键。 本文将用纯汇编揭示这个经典函数背后的指令级优化。
052-纯汇编写字串比较函数strcmpA
知识点:
__declspec(naked) 纯汇编
堆栈平衡
参数传递
用纯汇编封装函数strcmpA
__declspec(naked) int strcmpA(char* s1,char *s2)// scasw strcmpW
{
__asm
{
push ebp // esp+4+4 s1 //esp+4+8
mov ebp,esp //构建栈底
//mov al,0
xor al,al //eax=0
mov edi,[ebp+4+4]
mov ecx,-1 //0xFFFF FFFF
repnz scasb;
not ecx // '\0' 计算s1字串长度,指定repz循环次数
mov edi,[ebp+4+4]
mov esi,[ebp+4+8]
repz cmpsb // edi,esi
//[edi-1] [esi-1]
xor eax,eax
xor edx,edx
mov al,[edi-1]
mov dl,[esi-1]
sub eax,edx //相等eax=0,大于返回结果>0 小于<0
pop ebp //栈平衡
retn
}
}
#include "stdafx.h"
int strcmpA(char* s1,char *s2)
{
int i=0,j=0;
__asm
{
xor al,al ; //eax=0
mov edi,s1;
mov ecx,-1;
cld; //将DF标志位 置0
repnz scasb;
not ecx;
mov i,ecx; //i为s1的长度
mov edi,s2;
mov ecx,-1;
repnz scasb;
not ecx;
mov j,ecx; //j为s2的长度
cmp ecx,i; //如果s1和s2长度不一样,则跳转到end
jnz end;
mov edi,s1;
mov esi,s2;
repz cmpsb //如果直到ECX==0才结束,就表示字符串相同
cmp ecx,0;
jnz end;
mov eax,1;
jmp over;
end:
mov eax,0;
over:
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int i=0;
char *s1="abcde21";
char *s2="abcde21";
i=strcmpA(s1,s2);
printf("%d",i);
return 0;
}
053-STD和CLD,纯汇编写strcmpW
知识点:
__declspec(naked) 纯汇编
堆栈平衡
参数传递
用纯汇编封装函数strcmpW
STD和CLD指令
一、用纯汇编封装函数strcmpW
1、用repnz scasw计算字串长度
2、用repz cmpsw比较字串
3、把比较的结果存放在EAX里边返回
__declspec(naked) int strcmpw(WCHAR* s1,WCHAR *s2)// scasw strcmpW
{
__asm
{
push ebp
mov ebp,esp
// esp+4+4 s1 //esp+4+8 s2
xor ax,ax //在edi所在地址查找字节的
mov edi,[ebp+4+4]
mov ecx,-1 //0xFFFF FFFF
repnz scasw;
not ecx // '\0' 计算s1字串长度,指定repz循环次数
mov edi,[ebp+4+4]
mov esi,[ebp+4+8]
repz cmpsw // 每次比较2字节 (1个字)
xor eax,eax
xor edx,edx
mov ax,[edi-2]
mov dx,[esi-2]
sub eax,edx //相等eax=0,大于返回结果>0 小于<0
pop ebp
retn
}
二、方向标志位(DF相关指令) STD/CLD
STD => DF=1
CLD => DF=0
读取UNICODE字符串(宽字符):%ws
读取ASCII字符串:%s
#include "stdafx.h"
int strcmpA(wchar_t* s1,wchar_t *s2)
{
int i=0,j=0;
__asm
{
xor ax,ax;
mov edi,s1;
mov ecx,-1;
cld; //将DF标志位 置0
repnz scasw;
not ecx;
mov i,ecx; //i为s1的长度
mov edi,s2;
mov ecx,-1;
repnz scasw;
not ecx;
mov j,ecx; //j为s2的长度
cmp ecx,i; //如果s1和s2长度不一样,则跳转到end
jnz end;
mov edi,s1;
mov esi,s2;
repz cmpsw //如果直到ECX==0才结束,就表示字符串相同
cmp ecx,0;
jnz end;
mov eax,1;
jmp over;
end:
mov eax,0;
over:
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int i=0;
wchar_t *s1=L"ABCD";
wchar_t *s2=L"ABCD";
i=strcmpA(s1,s2);
printf("%d",i);
return 0;
}
计算机科学与技术 & 计算机网络技术:双专业课程体系完全导航指南
本系列目录
1、逆向工程基础:Ollydbg(OD)调试器实战与MOV指令寻址方式精讲
2、汇编语言核心概念精讲:从ADD、SUB、MOVSX/MOVZX到LEA与寄存器详解
3、x86汇编条件跳转指令完全解析:从CMP到有/无符号跳转与If实现
4、x86汇编函数调用完全解析:栈帧(EBP/ESP)构建与三种调用约定(cdecl/stdcall/fastcall)对比
5、汇编逆向还原核心:if-else与switch-case结构的识别与C代码重构
6、编译器优化揭秘:对比for循环的汇编实现与INC vs ADD指令的性能抉择
7、x86浮点运算基础:FPU寄存器、FLD/FSTP与FADD/FSUB等指令精讲
8、汇编位移指令全解与逆向实战:从SHR/SHL到ROL/ROR,逆向分析strcmp
9、汇编位运算指令精讲:掌握AND/OR/XOR/NOT四大核心操作
10、x86汇编字符串处理:SCASB/SCASW指令与REPNE/REPE重复前缀详解
11、汇编实战:用REPNZ SCASB与REPZ CMPSB从零实现strcmpA/W
12、x86汇编批量操作指令:LOOP循环控制与STOS/LODS串操作详解
更多推荐



所有评论(0)