先解釋部份曹操傳常用指令的意義。
cmp a,b 比較a與b
mov a,b 把b的值移入a,使a=b
retn 返回調用的程序
nop 無作用
(解釋:ultraedit打開編輯exe文件時你看到90,等同於組合語言語句nop)
call 調用副程式
je 或jz 若相等則跳
jne或jnz 若不相等則跳
jmp 無條件跳
jb 若小於則跳
ja 若大於則跳
jg 若大於則跳
jge 若大於等於則跳
jl 若小於則跳
jle 若小於等於則跳
pop 出棧
push 壓棧
ADD 加法.
INC 加 1.
SUB 減法.
DEC 減 1.
IMUL 整數乘法.
DIV 無符號除法.
IDIV 整數除法.
eax,ecx,edx,ebx,esp,ebp,esi,edi 這幾個都是32位元暫存器,用來存放數值。但是除了eax,ecx,edx,ebx,其他的不能亂用,否則容易出錯。
這是EAX、ECX、EDX、EBX暫存器的格式,以EAX來說明:
假設EAX=01234567,則AX=4567,AH=45,AL=67
以下是曹操傳"獲取連擊概率"代碼的範例解說:
00405CE6 /$ 55 push ebp
將ebp壓入堆棧
00405CE7 |. 8BEC mov ebp, esp
將esp的值移入ebp
00405CE9 |. 83EC 0C sub esp, 0C
esp = esp - 0C (0C是十六進位,也就是12。這行是為了空出三個暫存空間。每個空間小大為4,三個就是12。之後會用[ebp-n]來表示這些位置。前面的mov ebp,esp也是這個用意。)
00405CEC |. 894D F4 mov dword ptr [ebp-C], ecx
將ecx值移入第三個暫存空間[ebp-C],用[]引號括起來的,代表內存裡的值。例如ebp=23FFF0,[ebp-C]就是內存23FFE4裡的值。而這裡的ecx則儲存著"攻擊資訊"的內存位置。
00405CEF |. 8B45 F4 mov eax, dword ptr [ebp-C]
將[ebp-C]值移入eax。
00405CF2 |. 8B48 0C mov ecx, dword ptr [eax+C]
將[eax+C]值移入ecx,此時的[eax+C]存放著"攻擊方武將"的內存位置。
00405CF5 |. E8 37990300 call 0043F631
調用0043F631副程式。這又是另一個副程式,按回車可以進入查看,按 - 號即可返回。這個副程式是獲取武將ecx的爆發力,也就是攻擊方武將的爆發力。
00405CFA |. 8945 F8 mov dword ptr [ebp-8], eax
將eax移入[ebp-8],也就是第二個暫存位置。而這個eax則存放著攻擊方武將的爆發力。
00405CFD |. 8B4D F4 mov ecx, dword ptr [ebp-C]
將[ebp-C]值移入ecx。這[ebp-C]值存放著攻擊資訊的內存位置,還記得吧?
00405D00 |. 33D2 xor edx, edx
將edx清為0。
00405D02 |. 8A51 01 mov dl, byte ptr [ecx+1]
將[ecx+1]值移入dl (dl是edx的一部份,上面有解釋到),此時的[ecx+1]值存放著被攻擊方的武將編號。
00405D05 |. 8BCA mov ecx, edx
將edx值移入ecx。
00405D07 |. 6BC9 24 imul ecx, ecx, 24
將ecx乘與24,並將結果存進ecx。這個24代表戰場武將資訊裡,每個武將資料的間隔。
00405D0A |. 81C1 502C4B00 add ecx, 004B2C50
將ecx加上4B2C50。這個4B2C50是戰場武將內存的第一個武將位置。而ECX存放著"被攻擊方武將編號 * 24",加上4B2C50後,就是被攻擊方武將的內存位置。
00405D10 |. E8 1C990300 call 0043F631
調用43F631副程式,獲取武將ecx的爆發力,也就是獲取被攻擊方武將的爆發力。
00405D15 |. 8945 FC mov dword ptr [ebp-4], eax
將eax移入[ebp-4],也就是第一個暫存位置。而這個eax則存放著被攻擊方武將的爆發力。
00405D18 |. 8B45 FC mov eax, dword ptr [ebp-4]
將[ebp-4]移入eax。基本上這行是多餘的,曹操傳裡常常有這種多餘的代碼,可以空出來寫其他東西。
00405D1B |. 6BC0 03 imul eax, eax, 3
將eax * 3,並存入eax。
00405D1E |. 3945 F8 cmp dword ptr [ebp-8], eax
比較[ebp-8]和eax,[ebp-8]存放著攻擊方武將的爆發力。
00405D21 |. 72 04 jb short 00405D27
若[ebp-8] < eax,則跳轉到00405D27。也就是攻擊方武將爆發力 < 被攻擊方武將爆發力 * 3 ,則跳轉,否則繼續下一行。
00405D23 |. B0 64 mov al, 64
將64這個值移入al,這個al就代表著"連擊機率。也就是攻擊方武將爆發力 > 被攻擊方武將爆發力 * 3 ,則連擊機率為100%
00405D25 |. EB 3E jmp short 00405D65
無條件跳轉到00405D65
00405D27 |> 8B4D FC mov ecx, dword ptr [ebp-4]
將[ebp-4]值移入ecx。這行是從405D21跳轉過來的。而[ebp-4]存放著被攻擊方武將的爆發力。
00405D2A |. D1E1 shl ecx, 1
將ecx * 2。(shl就是乘與2的次方。例如shl ecx, 2,就是ecx * 4)
00405D2C |. 394D F8 cmp dword ptr [ebp-8], ecx
比較[ebp-8]值與ecx。[ebp-8]值存放著攻擊方武將的爆發力。
00405D2F |. 72 17 jb short 00405D48
如果[ebp-8] < ecx則跳轉到00405D48。也就是攻擊方武將爆發力 < 被攻擊方武將爆發力 * 2 ,則跳轉,否則繼續下一行。
00405D31 |. 8B55 FC mov edx, dword ptr [ebp-4]
將[ebp-4]移入edx。[ebp-4]存放著被攻擊方武將的爆發力。
00405D34 |. D1E2 shl edx, 1
將edx * 2。
00405D36 |. 8B45 F8 mov eax, dword ptr [ebp-8]
將[ebp-8]移入eax。[ebp-8]值存放著攻擊方武將的爆發力。
00405D39 |. 2BC2 sub eax, edx
將eax減去edx。
00405D3B |. 6BC0 50 imul eax, eax, 50
將eax乘與50,並存入eax
00405D3E |. 33D2 xor edx, edx
將edx清為0
00405D40 |. F775 FC div dword ptr [ebp-4]
將eax除與[ebp-4]。div這個指令固定是以eax來除,商數存於eax,餘數存於edx,所以使用前要先將edx清為0。
00405D43 |. 83C0 14 add eax, 14
將eax加上14。這個就是連擊機率。
上面幾行總結,就是在"攻擊方武將爆發力 > 被攻擊方武將爆發力 * 2"的情況下,機率公式為:
(攻擊方武將的爆發力 - 被攻擊方武將的爆發力 * 2) * 80 / 被攻擊方武將的爆發力 + 20
00405D46 |. EB 1D jmp short 00405D65
無條件跳轉到00405D65
00405D48 |> 8B45 F8 mov eax, dword ptr [ebp-8]
將[ebp-8]值移入eax。[ebp-8]存放什麼不需要解釋了吧? 這行是從00405D2F 跳轉來的。
00405D4B |. 3B45 FC cmp eax, dword ptr [ebp-4]
比較eax和[ebp-4]。[ebp-4]存放著...??自己想。
00405D4E |. 72 13 jb short 00405D63
如果eax < [ebp-4],則跳轉到00405D63。也就是攻擊方武將爆發力 < 被攻擊方武將爆發力,則跳轉,否則繼續下一行。
00405D50 |. 8B45 F8 mov eax, dword ptr [ebp-8]
將[ebp-8]移入eax
00405D53 |. 2B45 FC sub eax, dword ptr [ebp-4]
將eax減去[ebp-4]
00405D56 |. 6BC0 12 imul eax, eax, 12
將eax乘與12,並放入eax
00405D59 |. 33D2 xor edx, edx
將edx清零
00405D5B |. F775 FC div dword ptr [ebp-4]
將eax除與[ebp-4]
00405D5E |. 83C0 02 add eax, 2
將eax加2,這就是連擊機率。
上面幾行總結,就是在"攻擊方武將爆發力 > 被攻擊方武將爆發力"的情況下,機率公式為:
(攻擊方武將的爆發力 - 被攻擊方武將的爆發力) * 18 / 被攻擊方武將的爆發力 + 2
00405D61 |. EB 02 jmp short 00405D65
無條件跳轉到00405D65
00405D63 |> B0 01 mov al, 1
將1移入al,這是"攻擊方武將爆發力 < 被攻擊方武將爆發力"情況下的機率。
00405D65 |> 8BE5 mov esp, ebp
將ebp移入esp
00405D67 |. 5D pop ebp
將ebp從堆棧中取出
00405D68 \. C3 retn
返回調用的程序
最後這三行是曹操傳副程序的標準結尾。最後一行也有可能不一樣,以後再另外說明。
恭喜你很有耐心的看完了,也恭喜我終於打完了……
如果了解的人,不妨試著改變連擊公式吧!當然請記得備份……
ps.這是原版曹操傳的代碼,其他MOD可能有所不同,尤其是star175的,所以盡量以原版曹操傳來測試。
沒有留言:
張貼留言