ASM访问c结构的动态2d数组

时间:2016-11-29 16:07:28

标签: c arrays assembly nasm

以免我假设我有一个类似

的结构
struct color {
    int16_t r;
    int16_t g;
    int16_t b;
};

还有点数组

struct color** colors = (struct color**) malloc(rows*sizeof(struct color*));
for (int i=0; i < rows; i++) {
    colors[i] = (struct color*) malloc(columns*sizeof(struct color));
    for (int j=0; j < columns; j++) {
        colors[i][j].r=0;
        colors[i][j].g=0;
        colors[i][j].b=0;
    }
}

我想将它传递给函数

void some_function(struct color** colors);

颜色现在在rdi上。我想迭代那个数组并在assambler中将r加2,g加2,加3加b。我知道rdi是指向颜色的指针,[rdi]指向颜色[0],[rdi + 8]是指向颜色[1]的指针,但是如何访问颜色[1] [2] .r和颜色[1 ] [2]·G

1 个答案:

答案 0 :(得分:1)

  

[rdi]是指向颜色[0]的指针,[rdi + 8]是指向颜色[1]的指针,但是如何访问颜色[1] [2] .r和颜色[1] [2] .g

mov  rsi,[rdi + row*8]  ; rsi = pointer to single row data

mov  ax,[rsi + column*size_of_color + offset_of_r/g/b] ; value of r/g/b

rdi的使用情况来看,我猜您正在使用64b代码。

所以我猜color结构是8B对齐的,所以它的大小可能是24B,而[r, g, b]的偏移可能是[+0, +8, +16]

所以选择&#34; b&#34;代码为[13] [7]颜色的值为:

mov rsi,[rdi + 13*8]
mov eax,7 * 24
mov ax,[rsi + eax + 16] ; ax = "colors[13][7].b"

为什么我会使用像&#34; guess&#34;和&#34;可能&#34;朝向结构尺寸/偏移。因为那个C编译器的实现和配置依赖。我相信你想要的是让结构紧密地存储(即大小6B和偏移[+ 0,+ 2,+ 4])。

搜索您的编译器指令以实现这一点,这里有一些pragma documentation for gccattributes

struct color {
    int16_t r;
    int16_t g;
    int16_t b;
    // if you are not short of memory, consider to bump the size to 8B
    // int16_t padding2B;   // *8 multiplier is available in ASM addressing
                            // like mov ax,[rsi + ebx*8 + 2]
} __attribute__ ((packed));
// gcc will now compile this as 6B structure
// Performance warning:
// also it will stop assume anything about alignment
// so the C compiled machine code can be less optimal
// than for "unpacked" struct

正如您已经意识到的那样,2D阵列是ASM中的PITA,那么为什么不选择平面内存结构呢?特别是对于固定列大小为2的幂,平坦存储器结构不仅可以更简单地编码,而且还可以通过在连续存储器中具有行来获得相当大的性能提升。您的解决方案取决于malloc分配策略和碎片堆,您可能会在不同缓存页面中的每一行颜色结束,有几个额外的缓存未命中(比平面结构)。

struct color* colors = (struct color*) malloc(rows*columns*sizeof(struct color));
colors[row * columns + column].r = 0;

然后对于asm,你不仅要提供指针,还要提供columns大小(我无法看到如何省略rows任何有意义的事情)。

最后的说明。为什么不简单地在C中编写一些示例来访问该结构,编译它并检查生成的汇编程序,以了解如何访问该结构的成员(它也可能使用一些技巧如何执行这些* 24 /在您的目标平台上快速进行等等。)