0

I have this program:

#include <stdio.h>
#include <stdlib.h>

typedef struct item {
    int low; int high; char label[16];
} Item;

typedef struct item_coll {
    size_t length; Item *items[];
} ItemColl;

extern int find_first_in_range(ItemColl *ic, int rlow, int rhigh);

/*
char *find_first_in_range(ItemColl *ic, int rlow, int rhigh) {
    for (size_t i = 0; i < ic->length; i++)
        if (ic->items[i]->low >= rlow && ic->items[i]->high <= rhigh)
            return &ic->items[i]->label[0];
    return NULL;
}
* */

int main() {

    struct item fruits[] = {
        {10, 20, "Apple"},
        {12, 14, "Pear"},
        { 8, 12, "Banana"},
        { 2,  4, "Grape"},
        {15, 35, "Watermelon"}
    };

    struct item_coll *basket = malloc (sizeof *basket + 5 * sizeof *basket->items);
    basket->length = 5;

    for (size_t i = 0; i < 5; i++)  
        basket->items[i] = &fruits[i];

    int label = find_first_in_range (basket, 12, 15);
    printf ("%d\n", label);

    free (basket);

    return 0;
}

How do I access the different fields in fruits? Right now I was able to come up with the following information:

xor %r12, %r12
add $8, %r12
mov (%rdi, %r12), %rdi
mov (%rdi), %rax
ret
  • This will give me the 10 from Apple.

  • If I don't use %r12 and just load %rdi's value from memory, I get 5 (the basket's length).

  • If I add 16 to %r12, I get the 12 from Pear.

  • If I add 24 to %r12 I get the 8 from Banana.

How do I access for example the 20 in Apple? Shouldn't I just need to add 12 to %r12? It's giving me segmentation fault.

Vegas
  • 8,017
  • 1
  • 10
  • 14
  • To get the `20` you need to offset the **second** memory access, that is change `mov (%rdi), %rax` to `mov 4(%rdi), %eax`. Note that `int` is 4 bytes. – Jester Dec 30 '18 at 13:51
  • Why am I being able to get the `12` and the `8` without doing that? – Vegas Dec 30 '18 at 13:53
  • The second memory access is for the field in a single item. Since the `12` and the `8` are the first field they have offset zero. The `20` is the second field and has offset `4`. – Jester Dec 30 '18 at 13:56
  • How could you figure all that out? I don't know how the memory is supposed to be mapped when I look at the structure. – Vegas Dec 30 '18 at 13:58
  • I'm trying to get to the `Apple` string now and I can't see it. I'm trying to add `$12` instead of `$8` on `%r12`. I'm trying to change the return type to `* char` and to print the string. – Vegas Dec 30 '18 at 14:03
  • @Jester: I tried doing `mov 8(%rdi), %rax` and keeping the `add $8, %r12` and it still doesn't give me the string. – Vegas Dec 30 '18 at 14:09
  • That should give you the string, maybe you are printing it wrong. – Jester Dec 30 '18 at 14:15
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/185937/discussion-between-vegas-and-jester). – Vegas Dec 30 '18 at 14:18
  • You should try compiling your C function and looking at the resulting asm. See [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116). e.g. like this: https://godbolt.org/z/NrT2LF. And BTW, your code would probably be more efficient if `ItemColl` just had a pointer to an array of `Item` objects, instead of your current array of pointers where it takes two dereferences to get to the fields of each `Item` . To sort collections according to a key or something, then sure copying around 8-byte pointers instead of 32-byte objects is ok, esp. without AVX. – Peter Cordes Dec 31 '18 at 04:33

0 Answers0