For this x86 (Watcom 1997) assembly that loops over an array, Hexrays yields the following pseudo code:
lea eax, ds:0[ecx*4]
add eax, ecx
shl eax, 3
mov [esp+310h+iMulSize], eax
mov edx, [esp+310h+iMulSize]
mov eax, [esi+14h]
add edx, eax
mov eax, [esp+310h+v3Normal.x]
mov [edx], eax
mov edx, [esp+310h+iMulSize]
mov eax, [esi+14h]
add edx, eax
mov eax, [esp+310h+v3Normal.y]
mov [edx+4], eax
mov ebx, [esp+310h+iMulSize]
mov edx, [esi+14h]
add edx, ebx
mov eax, [esp+310h+v3Normal.z]
mov [edx+8], eax
iMulSize = sizeof(Tri) * i; // sizeof(Tri) = 0x28
pObject->paTris[i].v3Normal.x = v3Normal.x; // paTris at 0x14 in pObject
*(int *)((char *)&pObject->paTris->v3Normal.y + iMulSize) = v3Normal.y;
*(int *)((char *)&pObject->paTris->v3Normal.z + iMulSize) = v3Normal.z;
While easy to understand here, it leads to quite unreadable pseudo code in more complicated parts which also "pre-multiply" array indices by element size.
I tried to apply shifted pointers functionality, but don't know how for array indices. Is there a way I can enhance the output to become more readable as below? As seen in this 1998 version of the executable (which is not of analysis interest):
pObject->paTris[i].v3Normal.x = v3Normal.x;
pObject->paTris[i].v3Normal.y = v3Normal.y;
pObject->paTris[i].v3Normal.z = v3Normal.z;
imul eax, [ebp+i], 28h
mov edx, [ebp+pObject]
mov edx, [edx+14h]
add edx, eax
mov eax, [ebp+v3Normal.x]
mov [edx], eax
imul edx, [ebp+i], 28h
mov eax, [ebp+pObject]
mov eax, [eax+14h]
add edx, eax
mov eax, [ebp+v3Normal.y]
mov [edx+4], eax
imul edx, [ebp+i], 28h
mov eax, [ebp+pObject]
mov eax, [eax+14h]
add edx, eax
mov eax, [ebp+v3Normal.z]
mov [edx+8], eax