从编译器asm输出反向设计数组维度/结构布局?

问题描述 投票:2回答:1

在此代码中,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
c assembly x86 reverse-engineering
1个回答
3
投票

该结构具有以下对齐要求:

  • 一个char可以从任何字节开始
  • 一个short可以从偶数字节开始
  • int可以从byte开始,可以被4整除
  • 一个long可以从byte开始,可以被8整除

str1.y场是一个long,从184开始,这暗示,str1.x可以持有184180字节。

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 = 9B = 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。

© www.soinside.com 2019 - 2024. All rights reserved.