在此代码中,A和B是使用#define
定义的常量。 A和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;
}
为setVal
过程生成以下汇编代码:
setVal:
movslq 8(%rsi), %rax
addq 32(%rsi), %rax
movq %rax, 184(%rdi)
ret
答案 0 :(得分:3)
该结构具有以下对齐要求:
char
可以从任何字节开始short
可以从偶数字节开始int
可以从字节开始,可以被四个整除long
可以从字节开始,可以被8整除 str1.y
字段为long
,从184
开始,这意味着str1.x
可能包含184
或180
个字节
str2.t
字段为int
,从8
开始,这意味着str1.array
可能会从5
保持到8
个字节
str2.u
字段是long
,从32
开始,这意味着str2.S
可能会从14
保持到20
个字节
这是str1
结构字段的图表:
+---------------+---+--------+
| int x[A][B] | ? | long y |
+---------------+---+--------+
| 184 | 8 |
+-------------------+--------+
这是str2
字段的图表:
+---------------+---+-------+------------+---+--------+
| char array[B] | ? | int t | short S[A] | ? | long u |
+---------------+---+-------+------------+---+--------+
| 8 | 4 | 20 | 8 |
+-------------------+-------+----------------+--------+
之后,您应该解决以下系统:
177 <= 4 * A * B <= 184
5 <= B <= 8
14 <= A * 2 <= 20 // 7 <= A <= 10
答案是:A = 9
,B = 5
您可以使用遵循生成原始代码的编译器所使用的相同ABI /调用约定的编译器来测试您的答案(以及每个不等式的范围)。它使用8字节long
:注意addq
的64位操作数大小,而不是addl
和8字节存储。因此,我们可以推断它最有可能是x86-64 System V ABI,而不是Windows x86-64调用约定(使用4字节long
)。
Godbolt编译器资源管理器具有gcc,clang,ICC和MSVC。前3个目标Linux,但MSVC针对Windows调用约定,因此不同意结构布局,使用较小的long
需要较少的对齐。
Replacing int x[A][B]
with char t[177]
(or other sizes)证明177是最小值,184是导致商店到184(%rdi)
的最大尺寸。所以我们可以写176 < 4*A*B <= 184
。或者,为了将事物保持为4的倍数,180 <= 4*A*B <= 184
也或多或少是正确的;我们可以根据int
的大小排除177..179。