Reputation: 527
Lest assume I have a struct like
struct color {
int16_t r;
int16_t g;
int16_t b;
};
and also an array of points
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;
}
}
I want to pass it to a function
void some_function(struct color** colors);
colors are now on rdi. I want to iterate over that array and add 1 to r, 2 to g and 3 to b, in assambler. I know that rdi is pointer to colors, [rdi] is pointer to colors[0], [rdi + 8] is pointer to colors[1], but how to access colors[1][2].r and colors[1][2].g
Upvotes: 1
Views: 449
Reputation: 16586
[rdi] is pointer to colors[0], [rdi + 8] is pointer to colors[1], but how to access colors[1][2].r and colors[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
From usage of rdi
I guess you are working on 64b code.
So I guess the color
structure is 8B aligned, so it's size is probably 24B and offsets of [r, g, b]
will be probably [+0, +8, +16]
.
So to pick "b" value from [13][7] color the code would be:
mov rsi,[rdi + 13*8]
mov eax,7 * 24
mov ax,[rsi + eax + 16] ; ax = "colors[13][7].b"
Why am I using words like "guess" and "probably" toward structure size/offsets. Because that's C-compiler implementation and configuration dependent. I believe what you did want is to have the struct tightly memory packed (ie. size 6B and offsets [+0, +2, +4]).
Search for your compiler directive to achieve that, here is some pragma documentation for gcc and here attributes.
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
As you already realized, the 2D arrays are PITA in ASM, so why don't you go for flat memory structure? Especially with fixed columns size being some power of two the flat memory structure will be not just simpler to code for, but also it may receive considerable performance boost from having the rows in continuous memory. Your solution depends on malloc
allocation strategy and with fragmented heap you may end with each row of colors in different cache-page, having several additional cache-misses (than flat structure).
struct color* colors = (struct color*) malloc(rows*columns*sizeof(struct color));
colors[row * columns + column].r = 0;
Then for asm you have to provide not only the pointer, but also the columns
size (and I can't see how omitting rows
is possible for anything a bit meaningful either).
Final note. Why don't you simply write some example in C accessing that structure, compile it, and check the generated assembler, to get idea how to access members of the structure (it may also use some trick how to do those *24/etc in fast way on your target platform).
Upvotes: 1