大航海时代ol台服找Call记(十) 物品ID计算物品中文名称 (1)
第九篇找到了背包物品信息,但只有物品的ID和数量,并没有找到物品名称,继续:
GVOnline.exe+55D844 - 8D 4D FC - lea ecx,[ebp-04]
GVOnline.exe+55D847 - 51 - push ecx {参数3:堆栈地址1,作临时变量}
GVOnline.exe+55D848 - 8D 4D F8 - lea ecx,[ebp-08]
GVOnline.exe+55D84B - 51 - push ecx {参数2:堆栈地址2,作临时变量)
GVOnline.exe+55D84C - 56 - push esi {参数1: esi = 物品 ID }
GVOnline.exe+55D84D - 8D 88 843D0000 - lea ecx,[eax+00003D84] { ecx = 物品名称基址 1219664 }
GVOnline.exe+55D853 - E8 38DCBEFF - call GVOnline.exe+14B490 <------ 通用名称call
//Tab选中NPC、活动场景等获取名称均从此call取得)
GVOnline.exe+55D85C - 8B 70 04 - mov esi,[eax+04]
GVOnline.exe+55D85F - 85 F6 - test esi,esi
GVOnline.exe+55D861 - 74 1D - je GVOnline.exe+55D880
GVOnline.exe+55D863 - 83 7E 18 00 - cmp dword ptr [esi+18],00 { 0 }
GVOnline.exe+55D867 - 7E 0F - jle GVOnline.exe+55D878
GVOnline.exe+55D869 - FF 76 04 - push [esi+04]
GVOnline.exe+55D86C - 8D 46 08 - lea eax,[esi+08]
GVOnline.exe+55D86F - 50 - push eax
GVOnline.exe+55D870 - E8 BBD83A00 - call GVOnline.exe+90B130
GVOnline.exe+55D875 - 83 C4 08 - add esp,08 { 8 }
GVOnline.exe+55D878 - 8B 46 0C - mov eax,[esi+0C] { 宽松衫 }
GVOnline.exe+55D87B - 5E - pop esi
GVOnline.exe+55D87C - 8B E5 - mov esp,ebp
GVOnline.exe+55D87E - 5D - pop ebp
GVOnline.exe+55D87F - C3 - ret
...
//-------- 进入通用名称 call GVOnline.exe+14B490分析---------
GVOnline.exe+14B490 - 55 - push ebp
GVOnline.exe+14B491 - 8B EC - mov ebp,esp
GVOnline.exe+14B493 - 56 - push esi
GVOnline.exe+14B494 - 8B 75 08 - mov esi,[ebp+08] -----上层传入的参数1,物品ID
GVOnline.exe+14B497 - 57 - push edi
GVOnline.exe+14B498 - 68 1DF30100 - push 0001F31D { (0) }
GVOnline.exe+14B49D - 56 - push esi
GVOnline.exe+14B49E - 8B F9 - mov edi,ecx
GVOnline.exe+14B4A0 - E8 593F9500 - call GVOnline.exe+A9F3FE // --- ( id / 1f31d) eax = 商,edx = 余数
GVOnline.exe+14B4A5 - 69 D2 A7410000 - imul edx,edx,000041A7 { 16807 } 余数*41A7
GVOnline.exe+14B4AB - 69 C0 140B0000 - imul eax,eax,00000B14 { 2836 } 商*B14
GVOnline.exe+14B4B1 - 83 C4 08 - add esp,08 { 8 }
GVOnline.exe+14B4B4 - 2B D0 - sub edx,eax ------- edx = 余数41A7 - 商B14 ,记作HashID
GVOnline.exe+14B4B6 - 79 06 - jns GVOnline.exe+14B4BE <0?
GVOnline.exe+14B4B8 - 81 C2 FFFFFF7F - add edx,7FFFFFFF { 2147483647 } 调整下
GVOnline.exe+14B4BE - 8B 4D 10 - mov ecx,[ebp+10] --- //上层传入的参数3,存放 HashID
GVOnline.exe+14B4C1 - 8B C2 - mov eax,edx
GVOnline.exe+14B4C3 - 89 11 - mov [ecx],edx ---- 存入 HashID
GVOnline.exe+14B4C5 - 33 D2 - xor edx,edx
GVOnline.exe+14B4C7 - F7 77 08 - div [edi+08] -------EAX=HashID mod $11) >结果作为ID的Hash值,记作:HashKey [edi+8]=[基址ecx+8] =$11(哈希表条目数)
GVOnline.exe+14B4CA - 8B 45 0C - mov eax,[ebp+0C] 上层传入参数2
GVOnline.exe+14B4CD - 89 10 - mov [eax],edx -------存放 HashKey
GVOnline.exe+14B4CF - 8B 47 04 - mov eax,[edi+04] -----([基址ecx+4] = 哈希表首地址)
GVOnline.exe+14B4D2 - 85 C0 - test eax,eax
GVOnline.exe+14B4D4 - 74 1A - je GVOnline.exe+14B4F0
GVOnline.exe+14B4D6 - 8B 04 90 - mov eax,[eax+edx*4] ------- (哈希表首地址起,存有$11个条目的地址) eax=HashKey对应的条目地址
GVOnline.exe+14B4D9 - 85 C0 - test eax,eax
GVOnline.exe+14B4DB - 74 13 - je GVOnline.exe+14B4F0
GVOnline.exe+14B4DD - 8B 09 - mov ecx,[ecx] ---HashID
GVOnline.exe+14B4DF - 90 - nop
GVOnline.exe+14B4E0 - 39 48 0C - cmp [eax+0C],ecx ---与比较HashID
GVOnline.exe+14B4E3 - 75 04 - jne GVOnline.exe+14B4E9 ---不等跳,eax=[eax+08]
GVOnline.exe+14B4E5 - 39 30 - cmp [eax],esi ----相等,再比较ID是否一致
GVOnline.exe+14B4E7 - 74 09 - je GVOnline.exe+14B4F2 ---相等,找到。
GVOnline.exe+14B4E9 - 8B 40 08 - mov eax,[eax+08]
GVOnline.exe+14B4EC - 85 C0 - test eax,eax --- EAX=0? 没找到,跳出
GVOnline.exe+14B4EE - 75 F0 - jne GVOnline.exe+14B4E0
GVOnline.exe+14B4F0 - 33 C0 - xor eax,eax
GVOnline.exe+14B4F2 - 5F - pop edi
GVOnline.exe+14B4F3 - 5E - pop esi
GVOnline.exe+14B4F4 - 5D - pop ebp
GVOnline.exe+14B4F5 - C2 0C00 - ret 000C { 12 }
...
整理下:
ecx=0x1219664 (基地)
hashID = ((ID mod 1f31d)*41a7 - (ID div 1f31d) b14)
hashKey = hashID mod 0x11
addr = [[ecx]+haskKey4];
while(addr)
{
if (hashID == [addr+0c])
{
if(ID == [addr+0])
{
ItemChinese = [[addr+4]+0c]; //获取中文名称
return ItemChinese;
}
}
addr = [addr+08] ;
}
...

物品的中文名称统一存放在一个哈希表中,哈希表中共有0x11个条目。哈希表的地址指针即为获取物品名称的基址ecx = 0x1219664 ,[+4]=哈希表地址0x0558BBA0,[+8]=条目数0x11

[哈希表地址0x0558BBA0]为0x11个条目的首地址。
由上面的通用call分析可知
hashKey即为这0x11个条目的序号,如ID=0x10,经计算hashKey = 6,所以ID为0x10的物品在第06个条目中,条目地址即为蓝框中的0x05601b94

转到条目对应地址0x05601b94,由通用call分析可知,这里由一系列节点组成,每个节点长0x0c,其中:[+0]=ID,[+8]=下一个节点,[+0c]=hashID。
先判断[+0c] == haskID? ,相等再判断 ID==[+0];不相关则转到下一个节点继续判断直到相等。

这是找到时的图,[+0] == 0x10(ID),hashID = 0x041a70 。[+04] =0x052458B4即为ID为0x10物品的详细信息地址。

[+4]=ID,[+8]=数量, [+0c]=068328C0 =中文名称地址

浙公网安备 33010602011771号