Arrays 逆向工程与汇编代码解释

Arrays 逆向工程与汇编代码解释,arrays,assembly,x86,reverse-engineering,gnu-assembler,Arrays,Assembly,X86,Reverse Engineering,Gnu Assembler,我在逆向工程这个汇编代码以推断数组维度的值时遇到了困难 我被给予 struct vec3 { long z; int x; unsigned short y; }; struct vec3 array1[2][A]; struct vec3 array2[8][B]; int arrayfunc(int i1, int j1, int i2, int j2){ return array1[i1][j1].x + array1[i1][j1].y - array2[i2][

我在逆向工程这个汇编代码以推断数组维度的值时遇到了困难

我被给予

struct vec3 {
  long z;
  int x;
  unsigned short y;

};

struct vec3 array1[2][A];
struct vec3 array2[8][B];
int arrayfunc(int i1, int j1, int i2, int j2){
   return array1[i1][j1].x  + array1[i1][j1].y - array2[i2][j2].y;
}
这是提供的C代码,成员数据x、y、z的类型未知,但这是我推断出来的

arrayfunc:
    leaq    array1(%rip), %rax
    movslq  %ecx, %rcx
    movslq  %edx, %r10
    movslq  %r9d, %r9
    leaq    (%rcx,%rcx,2), %rdx
    movslq  %r8d, %r8
    movq    %rax, %rcx
    addq    %r10, %rdx
    salq    $4, %rdx
    movzwl  12(%rax,%rdx), %eax
    addl    8(%rcx,%rdx), %eax
    leaq    (%r9,%r8,2), %rdx
    leaq    array2(%rip), %rcx
    salq    $4, %rdx
    movzwl  12(%rcx,%rdx), %edx
    subl    %edx, %eax
    ret    
这里的问题是,我不确定如何从汇编代码中找到A和B的值

感谢所有帮助:)


谢谢:)

索引二维数组必须按
sizeof(struct vec3[a])
缩放第一个索引:
array1
是一个数组数组,每个较小的数组都有
a
元素。所以你看看asm,看看它乘以了什么

给定,
struct vec3数组1[2][A]
array1[i1][j1].x
与平面1D阵列的地址数学相同:
array1[(i1*a)+j1].x
。在C中,我们按元素而不是字节索引,因此asm也必须按
sizeof(struct vec3)
进行缩放。这显然是
sal$4,%reg
指令所做的,因为在填充对齐后,结构大小为16字节

请注意,前导尺寸
[2]
根本不在计算中;这只是告诉你你有多少总空间。是后面的尺寸设置了几何图形;不同行中相同列之间的跨距


如果您还没有看到C如何编译不同的A和B值,请尝试使用一些示例值,看看当您将A或B增加1时会发生什么变化。非常适合玩这样的东西

e、 g.使用质数3和7表示A和B,因此即使不改变数字,也可以看到哪些是它们的倍数

除了GCC太聪明了,它不会这么简单:例如,
RCX+RCX*2
=RCX*3,而不是使用
imul$3、%RCX、%rdx
。如果对A和B使用大的非简单数字,如12345,您将看到实际的
imul


我使用了
gcc-fpie
使其使用位置无关代码:一个RIP相对LEA将数组地址获取到寄存器中,而不是像
array1(%rcx,%rdx,2)
这样的寻址模式,这些模式要求数组地址(在.data或.bss部分)与机器代码中的32位符号扩展disp32相匹配


我还使用了
\uuuu属性(ms_abi))
来像代码一样使用Windows x64调用约定,因为Godbolt编译器资源管理器上的GCC是针对Linux的。(MSVC是Godbolt上唯一默认以Windows为目标的编译器,但它不会以AT&t语法输出。)

好的!这行代码“leaq array1(%rip),%rax”的作用是什么?在asm代码中,这部分“array1[i1][j1].x”对应于“@MeganDarcy”:它将
array1
的地址放入RAX中。类似于
mov$array1,%eax
,除了它在独立于位置的代码中工作(这是现代发行版上的gcc默认值-这就是为什么我在Godbolt链接中使用
-fpie
来匹配您的asm。没有它,您将看到gcc使用类似
array1(%rcx,%rdx)的寻址模式
,利用符号地址与其他寄存器一起用作32位符号扩展绝对地址的功能。)好的,谢谢!我说A是3,B是12,对吗?不太确定如何获得B值still@MeganDarcy字体不是12;这看起来与asm不同,需要更多的LEAs乘以3,然后再乘以4才能添加到
j1
。顺便说一句,我刚刚更新了我答案中的Godbolt链接以使用
\uuuu属性((ms_abi))
-很抱歉,昨天我没有注意到您的代码使用的是Windows调用约定,而不是x86-64 System V;您的第一个参数是RCX,而不是RDI。(我想写一个关于这类问题的一般答案,而不是为你做家庭作业)。无论如何,您可以通过查找到达R8D的var
i2
的乘数来找到B值。