1

Challenge #64

What does this code do?

An array of array[x][y] form is accessed here. Try to determine the dimensions of the array, at least partially, by finding y.

_array$ = 8
_x$ = 12
_y$ = 16
_f  PROC
    mov eax, DWORD PTR _x$[esp-4]
    mov edx, DWORD PTR _y$[esp-4]
    mov ecx, eax
    shl ecx, 4
    sub ecx, eax
    lea eax, DWORD PTR [edx+ecx*8]
    mov ecx, DWORD PTR _array$[esp-4]
    fld QWORD PTR [ecx+eax*8]
    ret 0
_f  ENDP

At first I think there is a mistake in the question. Because I only see three variables here, one for array address, the one x and one y, so I assume it's actually a 2d array of double, not a 3d as in "An array of array[x][y]".

Then I was stuck because eventually the program loads array[8y+192x], and x and y can be anything.

So I figured this must be a 3d array of double, with the third dimension given. I still couldn't figure it out so I tried to write my own program and use Godbolt to give me assembly. After a few trials I got something pretty close to the original program:

Something close

However I'm still having difficulty to match my program with the original question. I think I'm pretty close but how do I proceed from here? I have a hunch that y is also 24 in the original question, but not 100% sure.

1 Answer 1

2

This is somewhat of a symbolic simplification. If you execute code from start of the procedure, then just before ret these are the relevant changes to the state of the program - ignoring registers

float_st0          = @64[array + (y + x * 0x78) * 0x8]
float_stack_ptr    = float_stack_ptr + 0x1

where st0 has been loaded with a 64bit value from a location.

array + (y + x * 0x78) * 0x8

In a 1D array the way you access any index is

array + index * sizeof(member)

The size of the array member is 8 sizeof(double) here so the index is

y + x * 0x78

2D arrays are laid out linearly in memory. Accessing second dimension requires the size of first dimension to be known -

enter image description here

In the above example to access array[1][2] we need to access it like

array + sizeof(int) * (2 + 1 * 3)

In the op x is getting multiplied by 0x78 - so the size of the y dimension is 0x78 members.

Additionally I could replicate the problem code to an extent here

With this code and x86 MSVC v19.0, optimization flag /Ox

double load(double array[][0x78], int x, int y) {
    return array[x][y];
}

we get

_array$ = 8                                   ; size = 4
_x$ = 12                                                ; size = 4
_y$ = 16                                                ; size = 4
_load   PROC
        mov     ecx, DWORD PTR _x$[esp-4]
        mov     eax, DWORD PTR _y$[esp-4]
        shl     ecx, 4
        sub     ecx, DWORD PTR _x$[esp-4]
        lea     ecx, DWORD PTR [eax+ecx*8]
        mov     eax, DWORD PTR _array$[esp-4]
        fld     QWORD PTR [eax+ecx*8]
        ret     0
_load   ENDP

PS : I ran this through a miasm based simplification - code here

3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.