3

In this code, A and B are constants defined with #define. What are the values of A and B?

typedef struct {
    int x[A][B];
    long y;
} str1;

typedef struct {
    char array[B];
    int t;
    short S[A];
    long u;
} str2;

void setVal(str1 *p, str2 *q) {
    long v1 = q->t;
    long v2 = q->u;
    p->y = v1+v2;
}

The following assembly code is generated for the setVal procedure:

setVal:
    movslq  8(%rsi), %rax
    addq   32(%rsi), %rax
    movq     %rax, 184(%rdi)
    ret
4
  • 2
    What part of the assembly are you having trouble with? (Also: What do you mean by "formatted something like this"? Do you mean that you'd rather it not have been compiled for x86_64?) Commented Nov 9, 2015 at 5:52
  • actually disregard the last part, @duskwuff I just need help understanding the whole problem as a whole to be honest. the Process of finding what the values of A and B are. Commented Nov 9, 2015 at 5:59
  • 1
    Fun puzzle. Hint: it's all about structure padding. Commented Nov 9, 2015 at 6:46
  • Similar Q&A here, (which led to some confusion because the poster of that question didn't realize the code was different from this, and was asking for an explanation of why A==5 and B==6, when that's not the right answer for the other question.) Note that the new question is easier, because in that one you can solve for B right away without any ambiguity (since a narrow type follows an array of wide elements, so there won't be padding). Commented Apr 7, 2016 at 18:43

1 Answer 1

3

The structure has the following alignment requirements:

  • a char may start at any byte
  • a short may start at even byte
  • an int may start at byte, divisible by four
  • a long may start at byte, divisible by eight

The str1.y field is a long and starts at 184, this implies, that str1.x may hold either 184 or 180 bytes.

The str2.t field is an int and starts at 8, this implies, that str1.array may hold from 5 to 8 bytes.

The str2.u field is a long and starts at 32, this implies, that str2.S may hold from 14 to 20 bytes.

This is the diagram for str1 structure fields:

+---------------+---+--------+
|  int x[A][B]  | ? | long y |
+---------------+---+--------+
|        184        |    8   |
+-------------------+--------+

And this is the diagram for str2 fields:

+---------------+---+-------+------------+---+--------+
| char array[B] | ? | int t | short S[A] | ? | long u |
+---------------+---+-------+------------+---+--------+
|         8         |   4   |        20      |    8   |
+-------------------+-------+----------------+--------+

After that, you should solve the following system:

177 <= 4 * A * B <= 184
5 <= B <= 8
14 <= A * 2 <= 20      // 7 <= A <= 10

The answer is: A = 9, B = 5


You can test your answer (and the ranges for each inequality) using a compiler that follows the same ABI / calling convention used by the compiler that produced the original code. It uses 8-byte long: note the 64-bit operand size for the addq, instead of addl, and the 8-byte store. Thus, we can infer that it's most likely the x86-64 System V ABI, not the Windows x86-64 calling convention (which uses 4-byte long).

The Godbolt compiler explorer has gcc, clang, ICC, and MSVC. The first 3 target Linux, but MSVC targets the Windows calling convention and thus won't agree on struct layout with a smaller long requiring less alignment.

Replacing int x[A][B] with char t[177] (or other sizes) proves that 177 is the minimum and 184 is the maximum size that that leads to a store to 184(%rdi). So we could have written 176 < 4*A*B <= 184. Or, to keep things to multiples of 4, 180 <= 4*A*B <= 184 is also more or less correct; we can rule out 177..179 based on the size of int.

Sign up to request clarification or add additional context in comments.

2 Comments

Should be <= 4 * A * B <= 184 instead of <= A * B <= 184?
@A.Grow: your edit introduced an error. Were you thinking of 176 < 4*A*B <= 184? That's true with <, but not with <=. Try it on the Godbolt link I added to the question, and see that the asm output is different with only 176 bytes of array before str1::y.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.