如何通过x86程序集正确访问内存中的2D int数组

时间:2015-12-14 19:24:22

标签: arrays assembly

我一直在努力解决我提出的额外信用问题,但我在查找如何在x86程序集中正确访问2D int数组时遇到了问题。

我知道" 2d阵列"实际上是C中的1d数组,基于[i] [j]索引的偏移量,但我无法找到正确的访问方式。

所以基本上如果我将数组的基指针存储在f.rx2(1)中,那么偏移寄存器地址以访问数组的正确方法是什么,如[3] [2]? 等式或汇编指令可以。

1 个答案:

答案 0 :(得分:1)

  

如果我将数组的基指针存储在eax中,那会是什么   在[3] [2]访问数组的正确方法是什么?

首先,你需要知道它是一个C多维数组,还是它是一个指针数组(到数组)。

int foo (int cols, int multidimensional[][cols])
{ // C99-only, not C++
    return multidimensional[3][2]; // load rdi + 3*cols + 2
}
// or
int bar (int *pointers_to_rows[]) {
    return pointers_to_rows[3][2];  // load rdi + 3, then load that +2
}

gcc用-std=c99 -Wall -pedantic接受这个,所以我认为它是有效的C99,而不是GNU扩展。无论如何,你不能在godbolt上尝试它,因为C ++没有C99的可变维数组类型,而且godbolt只有c ++编译器,而不是C.

我猜你的意思是正确的多维数组,因为你说它们实际上是一维数组。就C的类型规则而言,这是不正确的,但在实际实现和存储方面是正确的。

无论如何,array[row][col]array[row*max_col + col]的语法糖。 (@ Ben的评论可能是在谈论Fortran,而不是C:C在Row major order中存储数组)。 max_col未存储在内存中的任何位置,仅作为数组类型的一部分。 (并且C是静态类型的,没有反射,所以此信息仅出现在二进制文件中的调试符号中)。这就是为什么我的示例函数需要它作为函数参数。 你的问题无法解决,因为你问的是如何在没有数组维度的情况下做到这一点

gcc --std=gnu99 /tmp/foo.c -O3 -masm=intel -S -o-将C编译为:

;; comments added manually.  -fverbose-asm isn't *this* helpful :P
foo:  ; (int cols, int multidimensional[][cols])
        movsx   rdi, edi              ; the ABI doesn't require clearing upper bits when passing values that don't fill registers
        lea     rax, [rdi+rdi*2]      ; rax = cols*3
        mov     eax, DWORD PTR [rsi+8+rax*4]  ; return rsi[cols*3*sizeof(int) + 2*sizeof(int)]
        ret

bar:  ; (int *pointers_to_rows[])
        mov     rax, QWORD PTR [rdi+24]  ; 24 = 3 * sizeof(pointer)
        mov     eax, DWORD PTR [rax+8]   ; 8  = 2*sizeof(int)
        ret

像往常一样,查看某些内容的最简单方法是查看编译器的功能。