逆向之KMP算法
版本:Release
优化选项:O2
调试工具:OD
源码:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define MAX_SIZE 100
- char fail[MAX_SIZE];
- void failure(char* pat)
- {
- int n=strlen(pat);
- int i,j;
- fail[0]=-1;
- for(j=1;j<n;j++)
- {
- i=fail[j-1];
- while((pat[i+1]!=pat[j])&&(i>=0))
- i=fail[i];
- if(pat[i+1]==pat[j])
- fail[j]=i+1;
- else
- fail[j]=-1;
- }
- }
- int match(char *string,char *pat)
- {
- int lenp,lens,i,j;
- failure(pat);
- i=j=0;
- lens=strlen(string);
- lenp=strlen(pat);
- while(i<lens&&j<lenp)
- {
- if(string[i]==pat[j])
- {
- i++;j++;
- }
- else
- if(j==0) i++;
- else
- j=fail[j-1]+1;
- }
- return j==lenp?i-lenp:-1;
- }
- int main()
- {
- char s[100]="abcdsdfsdfassdfwefjkjfelkf";
- char a[10]="dsdf";
- int q=match(s,a);
- printf("%d",q);
- system("pause");
- return 0;
- }
- match函数的反汇编
- 00211060 >/$ 53 push ebx
- 00211061 |. 55 push ebp
- 00211062 |. 8B6C24 10 mov ebp, dword ptr [esp+10] ; 第二个参数
- 00211066 |. 56 push esi
- 00211067 |. 57 push edi
- 00211068 |. 8BF5 mov esi, ebp
- 0021106A |. E8 91FFFFFF call failure ; 这个函数只有一个参数且存在esi中
- 0021106F |. 8B4424 14 mov eax, dword ptr [esp+14] ; 第一个参数
- 00211073 |. 33D2 xor edx, edx
- 00211075 |. 33FF xor edi, edi
- 00211077 |. 8D58 01 lea ebx, dword ptr [eax+1]
- 0021107A |. 8D9B 00000000 lea ebx, dword ptr [ebx]
- 00211080 |> 8A08 /mov cl, byte ptr [eax]
- 00211082 |. 40 |inc eax
- 00211083 |. 84C9 |test cl, cl
- 00211085 |.^ 75 F9 \jnz short 00211080
- 00211087 |. 8BCD mov ecx, ebp ; 第二个参数传到ecx
- 00211089 |. 2BC3 sub eax, ebx ; 获得字符串长度
- 0021108B |. 8D71 01 lea esi, dword ptr [ecx+1]
- 0021108E |. 8BFF mov edi, edi
- 00211090 |> 8A19 /mov bl, byte ptr [ecx]
- 00211092 |. 41 |inc ecx
- 00211093 |. 84DB |test bl, bl
- 00211095 |.^ 75 F9 \jnz short 00211090
- 00211097 |. 2BCE sub ecx, esi ; 获得第二个字符串长度
- 00211099 |. 85C0 test eax, eax ; 设第一个参数长度len1,第二个参数len2,则这里就是判定len1>0
- 0021109B |. 7E 29 jle short 002110C6
- 0021109D |. 8D49 00 lea ecx, dword ptr [ecx]
- 002110A0 |> 3BD1 /cmp edx, ecx ; edx随着内部循环而改变,底部的cmp中edi随着内部循环改变,所以特别关注这2个寄存器
- 002110A2 |. 7D 24 |jge short 002110C8
- 002110A4 |. 8B7424 14 |mov esi, dword ptr [esp+14] ; esi=第1个参数
- 002110A8 |. 8A1C37 |mov bl, byte ptr [edi+esi] ; 取第1个数组下标为edi的值
- 002110AB |. 3A1C2A |cmp bl, byte ptr [edx+ebp] ; 与第2个数组下标为edx的值比较
- 002110AE |. 75 03 |jnz short 002110B3
- 002110B0 |. 47 |inc edi ; 下标自增
- 002110B1 |. EB 0E |jmp short 002110C1
- 002110B3 |> 85D2 |test edx, edx
- 002110B5 |. 75 03 |jnz short 002110BA
- 002110B7 |. 47 |inc edi
- 002110B8 |. EB 08 |jmp short 002110C2
- 002110BA |> 0FBE92 6F3321>|movsx edx, byte ptr [edx+21336F] ; edx=faile[edx]
- 002110C1 |> 42 |inc edx ; 下标自增
- 002110C2 |> 3BF8 |cmp edi, eax
- 002110C4 |.^ 7C DA \jl short 002110A0
- 002110C6 |> 3BD1 cmp edx, ecx
- 002110C8 |> 75 09 jnz short 002110D3 ; 这里2种返回情况其实就是len2==edx?edi-len2:-1;
- 002110CA |. 2BF9 sub edi, ecx
- 002110CC |. 8BC7 mov eax, edi
- 002110CE |. 5F pop edi
- 002110CF |. 5E pop esi
- 002110D0 |. 5D pop ebp
- 002110D1 |. 5B pop ebx
- 002110D2 |. C3 retn
- 002110D3 |> 5F pop edi
- 002110D4 |. 5E pop esi
- 002110D5 |. 5D pop ebp
- 002110D6 |. 83C8 FF or eax, FFFFFFFF
- 002110D9 |. 5B pop ebx
- 002110DA \. C3 retn
- 失配数组获得函数failure
- 00211000 >/$ 8BC6 mov eax, esi ; esi中存储模式串地址
- 00211002 |. 8D50 01 lea edx, dword ptr [eax+1]
- 00211005 |> 8A08 /mov cl, byte ptr [eax]
- 00211007 |. 40 |inc eax
- 00211008 |. 84C9 |test cl, cl
- 0021100A |.^ 75 F9 \jnz short 00211005
- 0021100C |. 2BC2 sub eax, edx ; 上面几个指令到这里获得字符串长度
- 0021100E |. 57 push edi
- 0021100F |. 8BF8 mov edi, eax
- 00211011 |. B9 01000000 mov ecx, 1
- 00211016 |. 3BF9 cmp edi, ecx ; if (len>1)
- 00211018 |. C605 70332100>mov byte ptr [fail], 0FF ; fail[0]=-1
- 0021101F |. 7E 3D jle short 0021105E
- 00211021 |> 0FBE81 6F3321>/movsx eax, byte ptr [ecx+21336F] ; eax=fail[ecx-1]
- 00211028 |. 8A1431 |mov dl, byte ptr [ecx+esi]
- 0021102B |. 385406 01 |cmp byte ptr [esi+eax+1], dl ; if a[eax+1]!=a[ecx]
- 0021102F |. 74 17 |je short 00211048
- 00211031 |> 85C0 |/test eax, eax
- 00211033 |. 7C 0D ||jl short 00211042
- 00211035 |. 0FBE80 703321>||movsx eax, byte ptr [eax+fail]
- 0021103C |. 385406 01 ||cmp byte ptr [esi+eax+1], dl
- 00211040 |.^ 75 EF |\jnz short 00211031 ; while(eax>0) eax=fail[eax];if(a[eax+1]==a[ecx]) break;
- 00211042 |> 385406 01 |cmp byte ptr [esi+eax+1], dl
- 00211046 |. 75 0A |jnz short 00211052
- 00211048 |> FEC0 |inc al
- 0021104A |. 8881 70332100 |mov byte ptr [ecx+fail], al ; fail[ecx]=eax+1
- 00211050 |. EB 07 |jmp short 00211059
- 00211052 |> C681 70332100>|mov byte ptr [ecx+fail], 0FF ; fail[ecx]=-1
- 00211059 |> 41 |inc ecx
- 0021105A |. 3BCF |cmp ecx, edi
- 0021105C |.^ 7C C3 \jl short 00211021 ; for(ecx=1;ecx<len;ecx++)
- 0021105E |> 5F pop edi
- 0021105F \. C3 retn
逆向之hanoi塔
没耐心逆复杂的了,就搞搞这个递归的
版本:Release
优化选项:O2
调试工具:OD
源码:
- //Hanoi塔(递归版本)
- #include <stdio.h>
- #include <stdlib.h>
- #define Tower1 1
- #define Tower2 2
- #define Tower3 3
- void towers_of_hanoi(int, int, int, int);
- int main(){
- int n_disks;
- printf("Number of disks: ");
- scanf("%d", &n_disks);
- printf("Disk, source, and destination towers listed below\n");
- printf("%12s%10s%15s\n", "Disk No", "Source","Destination");
- towers_of_hanoi(n_disks,Tower1,Tower3,Tower2);
- system("pause");
- return 0;
- }
- void towers_of_hanoi(int n_disks, int source, int dest, int spare){
- if (n_disks == 1 )
- printf("%10d%10d%10d\n", n_disks, source, dest);
- else {
- /*move a disk from source to spare*/
- towers_of_hanoi(n_disks-1,source,spare,dest);
- printf("%10d%10d%10d\n", n_disks, source, dest);
- /*move a disk from spare to destination tower*/
- towers_of_hanoi(n_disks-1,spare,dest,source);
- }
- }
- towers_of_hanoi函数,这里的递归经过优化后不太清楚。。。
- 01211061 |. 8B7424 08 mov esi, dword ptr [esp+8] ; 第一个参数,即盘子数
- 01211065 |. 57 push edi
- 01211066 |. 8B7C24 10 mov edi, dword ptr [esp+10] ; 第2个参数
- 0121106A |. 83FE 01 cmp esi, 1
- 0121106D |. 74 3A je short 012110A9 ; 盘子数等于1
- 0121106F |. 53 push ebx
- 01211070 |. 55 push ebp
- 01211071 |. 8B6C24 20 mov ebp, dword ptr [esp+20] ; 第4个参数
- 01211075 |> 8B4424 1C /mov eax, dword ptr [esp+1C] ; 第3个参数
- 01211079 |. 50 |push eax ; 假设原函数f(a,b,c,d),那么这里的调用就是f(a,b,d,c)
- 0121107A |. 55 |push ebp
- 0121107B |. 8D5E FF |lea ebx, dword ptr [esi-1]
- 0121107E |. 57 |push edi
- 0121107F |. 53 |push ebx ; ebx=esi-1
- 01211080 |. E8 DBFFFFFF |call towers_of_hanoi ; 代码中只递归一次,另外一次被优化掉了,优化成这个循环
- 01211085 |. 8B4C24 2C |mov ecx, dword ptr [esp+2C]
- 01211089 |. 51 |push ecx ; /<%10d>
- 0121108A |. 57 |push edi ; |<%10d>
- 0121108B |. 56 |push esi ; |<%10d>
- 0121108C |. 68 74212101 |push 01212174 ; |format = "%10d%10d%10d",LF,""
- 01211091 |. FF15 9C202101 |call dword ptr [<&MSVCR90.printf>] ; \printf
- 01211097 |. 8BC7 |mov eax, edi ; 这里交换参数准备下一次调用也就是f(a,d,c,b)
- 01211099 |. 8BF3 |mov esi, ebx ; esi=esi-1作为下一次判断条件
- 0121109B |. 83C4 20 |add esp, 20
- 0121109E |. 8BFD |mov edi, ebp
- 012110A0 |. 8BE8 |mov ebp, eax
- 012110A2 |. 83FE 01 |cmp esi, 1
- 012110A5 |.^ 75 CE \jnz short 01211075
- 012110A7 |. 5D pop ebp
- 012110A8 |. 5B pop ebx
- 012110A9 |> 8B5424 14 mov edx, dword ptr [esp+14] ; 第3个参数
- 012110AD |. 52 push edx ; /<%10d>
- 012110AE |. 57 push edi ; |<%10d>
- 012110AF |. 56 push esi ; |<%10d>
- 012110B0 |. 68 74212101 push 01212174 ; |format = "%10d%10d%10d",LF,""
- 012110B5 |. FF15 9C202101 call dword ptr [<&MSVCR90.printf>] ; \printf
- 012110BB |. 83C4 10 add esp, 10
- 012110BE |. 5F pop edi
- 012110BF |. 5E pop esi
- 012110C0 \. C3 retn
//Hanoi塔(递归版本)
#include <stdio.h>
#include <stdlib.h>
#define Tower1 1
#define Tower2 2
#define Tower3 3
void towers_of_hanoi(int, int, int, int);
int main(){
int n_disks;
printf("Number of disks: ");
scanf("%d", &n_disks);
printf("Disk, source, and destination towers listed below\n");
printf("%12s%10s%15s\n", "Disk No", "Source","Destination");
towers_of_hanoi(n_disks,Tower1,Tower3,Tower2);
system("pause");
return 0;
}
void towers_of_hanoi(int n_disks, int source, int dest, int spare){
if (n_disks == 1 )
printf("%10d%10d%10d\n", n_disks, source, dest);
else {
/*move a disk from source to spare*/
towers_of_hanoi(n_disks-1,source,spare,dest);
printf("%10d%10d%10d\n", n_disks, source, dest);
/*move a disk from spare to destination tower*/
towers_of_hanoi(n_disks-1,spare,dest,source);
}
}
towers_of_hanoi函数,这里的递归经过优化后不太清楚。。。
01211061 |. 8B7424 08 mov esi, dword ptr [esp+8] ; 第一个参数,即盘子数
01211065 |. 57 push edi
01211066 |. 8B7C24 10 mov edi, dword ptr [esp+10] ; 第2个参数
0121106A |. 83FE 01 cmp esi, 1
0121106D |. 74 3A je short 012110A9 ; 盘子数等于1
0121106F |. 53 push ebx
01211070 |. 55 push ebp
01211071 |. 8B6C24 20 mov ebp, dword ptr [esp+20] ; 第4个参数
01211075 |> 8B4424 1C /mov eax, dword ptr [esp+1C] ; 第3个参数
01211079 |. 50 |push eax ; 假设原函数f(a,b,c,d),那么这里的调用就是f(a,b,d,c)
0121107A |. 55 |push ebp
0121107B |. 8D5E FF |lea ebx, dword ptr [esi-1]
0121107E |. 57 |push edi
0121107F |. 53 |push ebx ; ebx=esi-1
01211080 |. E8 DBFFFFFF |call towers_of_hanoi ; 代码中只递归一次,另外一次被优化掉了,优化成这个循环
01211085 |. 8B4C24 2C |mov ecx, dword ptr [esp+2C]
01211089 |. 51 |push ecx ; /<%10d>
0121108A |. 57 |push edi ; |<%10d>
0121108B |. 56 |push esi ; |<%10d>
0121108C |. 68 74212101 |push 01212174 ; |format = "%10d%10d%10d",LF,""
01211091 |. FF15 9C202101 |call dword ptr [<&MSVCR90.printf>] ; \printf
01211097 |. 8BC7 |mov eax, edi ; 这里交换参数准备下一次调用也就是f(a,d,c,b)
01211099 |. 8BF3 |mov esi, ebx ; esi=esi-1作为下一次判断条件
0121109B |. 83C4 20 |add esp, 20
0121109E |. 8BFD |mov edi, ebp
012110A0 |. 8BE8 |mov ebp, eax
012110A2 |. 83FE 01 |cmp esi, 1
012110A5 |.^ 75 CE \jnz short 01211075
012110A7 |. 5D pop ebp
012110A8 |. 5B pop ebx
012110A9 |> 8B5424 14 mov edx, dword ptr [esp+14] ; 第3个参数
012110AD |. 52 push edx ; /<%10d>
012110AE |. 57 push edi ; |<%10d>
012110AF |. 56 push esi ; |<%10d>
012110B0 |. 68 74212101 push 01212174 ; |format = "%10d%10d%10d",LF,""
012110B5 |. FF15 9C202101 call dword ptr [<&MSVCR90.printf>] ; \printf
012110BB |. 83C4 10 add esp, 10
012110BE |. 5F pop edi
012110BF |. 5E pop esi
012110C0 \. C3 retn
经过反复反复反复观察观察实例实例。。。比如第一次参数f(a,b,c,d); 那么循环处调用的其实是第一次f(a,b,d,c),下一次循环就是f(a,d,b,c)
而这个f(a,d,b,c)其实就是源码的第二次递归调用后的第一次递归调用,也就是f(a,d,c,b),进入这个后第一次就是f(a,d,b,c)其实就跟优化后的循环调用一样了,使得所有的第二次递归都变成了第一次递归的样子,语言比较难描述。。。
贴完了。。。