我貼出程式碼段。。不再寫序號產生器了,演算法很簡單,你看看應該就會了 (7千字)

看雪資料發表於2001-01-04

程式碼分析:

    這是一個Fn(Name)+Fc(Company) = Fs(Code)的模式,也就是說將輸入的Name、Company和Code分別進行運算,如果
Name和Company的運算後的值相加等於Code運算後的值,那麼就可以了。

    全文分四部分,就是講Fn(Name)、Fc(Company)、Fs(Code)以及輸入是否正確的判斷地點。


第一部分:―― Fs(Code) 程式碼端如下:

:0040BA60 83EC08                  sub esp, 00000008
:0040BA63 89542404                mov dword ptr [esp+04], edx
:0040BA67 53                      push ebx
:0040BA68 C744240400000000        mov [esp+04], 00000000
:0040BA70 56                      push esi
:0040BA71 57                      push edi
:0040BA72 55                      push ebp
:0040BA73 BE01000000              mov esi, 00000001 //將esi置1,算Fs(Code)時要用到
:0040BA78 51                      push ecx
:0040BA79 8BE9                    mov ebp, ecx  // ebp = 輸入Code的位置Offset
:0040BA7B FF15F4134100            call dword ptr [004113F4]
:0040BA81 8D78FF                  lea edi, dword ptr [eax-01]  // edi=Code長度
:0040BA84 85FF                    test edi, edi
:0040BA86 7C3B                    jl 0040BAC3

:0040BA88 8A5C3D00                mov bl, byte ptr [ebp+edi// 將Code中的字元賦給bl
:0040BA8C 80FB30                  cmp bl, 30      |
:0040BA8F 7209                    jb 0040BA9A      | 判斷Code是不是數字,在這裡說明一下,判斷Code必須全部為數字
:0040BA91 80FB39                  cmp bl, 39      | 的Call在前面,在此省略
:0040BA94 7704                    ja 0040BA9A      |
:0040BA96 85FF                    test edi, edi  //看字元是否運算完?是從後到前運算的
:0040BA98 7D0E                    jge 0040BAA8

:0040BA9A B914D44000              mov ecx, 0040D414
:0040BA9F 8B542414                mov edx, dword ptr [esp+14]
:0040BAA3 E848FBFFFF              call 0040B5F0

:0040BAA8 33C0                    xor eax, eax
:0040BAAA 8D0CB6                  lea ecx, dword ptr [esi+4*esi// ecx = esi * 5
:0040BAAD 8AC3                    mov al, bl 
:0040BAAF 83E830                  sub eax, 00000030  //取十進位制數字值,
:0040BAB2 0FAFC6                  imul eax, esi
:0040BAB5 8D344D00000000          lea esi, dword ptr [2*ecx+00000000]  // esi = ecx * 2
:0040BABC 01442410                add dword ptr [esp+10], eax  // [esp+10]放累加和
:0040BAC0 4F                      dec edi
:0040BAC1 79C5                    jns 0040BA88

:0040BAC3 8B442410                mov eax, dword ptr [esp+10]  // 此Call將運算完後的值返回到 eax
:0040BAC7 5D                      pop ebp
:0040BAC8 5F                      pop edi
:0040BAC9 5E                      pop esi
:0040BACA 5B                      pop ebx
:0040BACB 83C408                  add esp, 00000008
:0040BACE C3                      ret



第二部分:Fn(Name) 和 Fc(Company) 的程式碼段:
:00406790 53                      push ebx
:00406791 56                      push esi
:00406792 668BD9                  mov bx, cx
:00406795 57                      push edi
:00406796 55                      push ebp
:00406797 8BF2                    mov esi, edx  // esi 放 Name 或 Company 的位置偏移
:00406799 85F6                    test esi, esi
:0040679B 7475                    je 00406812
:0040679D 803E00                  cmp byte ptr [esi], 00  // 判斷是否為空?
:004067A0 7470                    je 00406812
:004067A2 8BFE                    mov edi, esi
:004067A4 B9FFFFFFFF              mov ecx, FFFFFFFF
:004067A9 2BC0                    sub eax, eax
:004067AB F2                      repnz
:004067AC AE                      scasb
:004067AD F7D1                    not ecx
:004067AF 49                      dec ecx  // ecx放字串長度
:004067B0 6685DB                  test bx, bx
:004067B3 7444                    je 004067F9
:004067B5 6683FB01                cmp bx, 0001
:004067B9 743E                    je 004067F9
:004067BB 0FB7FB                  movzx edi, bx
:004067BE 8BC7                    mov eax, edi
:004067C0 99                      cdq
:004067C1 F7F9                    idiv ecx
:004067C3 0FBE0416                movsx eax, byte ptr [esi+edx]
:004067C7 0FAFC2                  imul eax, edx
:004067CA 0FAFC7                  imul eax, edi
:004067CD 03C1                    add eax, ecx
:004067CF 33D2                    xor edx, edx // 置0,即從第一個字元開始處理
:004067D1 85C9                    test ecx, ecx
:004067D3 7E19                    jle 004067EE
:004067D5 8BD9                    mov ebx, ecx
:004067D7 2BDF                    sub ebx, edi
:004067D9 0FBE3C16                movsx edi, byte ptr [esi+edx] // edi放字串的單個字元
:004067DD 8BEB                    mov ebp, ebx
:004067DF 2BEA                    sub ebp, edx
:004067E1 42                      inc edx
:004067E2 83C56F                  add ebp, 0000006F
:004067E5 0FAFFD                  imul edi, ebp
:004067E8 03C7                    add eax, edi
:004067EA 3BCA                    cmp ecx, edx
:004067EC 7FEB                    jg 004067D9  // 是否全部運算完?
:004067EE 85C0                    test eax, eax
:004067F0 7D25                    jge 00406817
:004067F2 F7D8                    neg eax  // 如果為負則取補
:004067F4 5D                      pop ebp
:004067F5 5F                      pop edi
:004067F6 5E                      pop esi
:004067F7 5B                      pop ebx
:004067F8 C3                      ret

:00406817 5D                      pop ebp  |
:00406818 5F                      pop edi  |
:00406819 5E                      pop esi  | 此段程式碼我怎麼也看不明白 ―― 畫蛇添足?  *_^
:0040681A 5B                      pop ebx  |
:0040681B C3                      ret      |


第三部分:Fn(Name) + Fc(Company)的部分在:
:00406820 53                      push ebx
:00406821 56                      push esi
:00406822 57                      push edi
:00406823 8BD9                    mov ebx, ecx
:00406825 668BCA                  mov cx, dx
:00406828 668BFA                  mov di, dx
:0040682B 8B542410                mov edx, dword ptr [esp+10] // edx = Name的偏移
:0040682F 6681E1FF00              and cx, 00FF
:00406834 66C1EF08                shr di, 08
:00406838 E853FFFFFF              call 00406790  // Fn()
:0040683D 668BCF                  mov cx, di
:00406840 8BF0                    mov esi, eax  // 運算和先放到 esi種暫存
:00406842 6685C9                  test cx, cx
:00406845 7517                    jne 0040685E
:00406847 8B542414                mov edx, dword ptr [esp+14]
:0040684B E840FFFFFF              call 00406790
:00406850 8D0C33                  lea ecx, dword ptr [ebx+esi]
:00406853 5F                      pop edi
:00406854 0FAFC8                  imul ecx, eax
:00406857 8BC1                    mov eax, ecx
:00406859 5E                      pop esi
:0040685A 5B                      pop ebx
:0040685B C20800                  ret 0008
:0040685E 6641                    inc cx
:00406860 8B542414                mov edx, dword ptr [esp+14]  // edx = Company的偏移
:00406864 E827FFFFFF              call 00406790
:00406869 03C6                    add eax, esi  // Fn(Name) + Fc(Company)
:0040686B 5F                      pop edi
:0040686C 03C3                    add eax, ebx
:0040686E 5E                      pop esi
:0040686F 5B                      pop ebx
:00406870 C20800                  ret 0008


第四部分:輸入是否正確的判斷地點
:00406CF8 8BE8                    mov ebp, eax  // ebp = Fn(Name) + Fc(Company)
:00406CFA 2BEE                    sub ebp, esi  // esi = Fs(Code)
:00406CFC 85ED                    test ebp, ebp
:00406CFE 7429                    je 00406D29  // 相等就行了


    演算法是不是很簡單?看看就會了,如果還是有疑問的話,那麼動態跟蹤好了。。呵呵

相關文章