如何从汇编代码中反向设计C整数类型?

时间:2018-01-13 18:02:02

标签: c assembly x86 reverse-engineering

考虑以下C函数原型,其中num_t是使用typedef声明的数据类型:

void store_prod(num_t *dest, unsigned x, num_t y) {
 *dest = x*y;
}

gcc生成以下汇编代码,实现计算主体: 什么数据类型是num_t

正确的答案是num_tunsigned long long,但我真的不明白为什么,我们将非常感谢任何帮助!!

# dest  at %ebp +8, x at %ebp +12, y at %ebp +16
movl  12(%ebp), %eax
movl  20(%ebp), %ecx
imull %eax, %ecx
mull  16(%ebp)
leal  (%ecx,%edx), %edx
movl  8(%ebp), %ecx
movl  %eax, (%ecx)
movl  %edx, 4(%ecx)

1 个答案:

答案 0 :(得分:4)

从使用(%ebp)寻址模式可以看出这是32位代码,而不是x86-64。

在32位模式下,unsigned long long是唯一的64位无符号整数类型,在任何常见的ABI中。 (例如,在Linux上使用的i386 System V ABI)。 long是32位。

我们可以告诉num_t是一个64位整数类型,因为它是从整数乘法和加法的结果中存储在两个32位的一半中。

我们可以告诉它它是unsigned整数类型,因为gcc在mul和{{1}的低半部分之间使用了imul而不是x }}。 (将yimul %eax, %ecx的上半部分相乘的2操作数x与有符号或无符号的二进制操作相同:仅全乘(N x N => 2N位)关心签名。)

IDK为什么gcc会使用y代替leal (%ecx,%edx), %edx。也许你用add %ecx, %edx或其他东西编译?保留标志是不必要的。

无论如何,它是普通的64 x 32 => 64位扩展精度乘法。

这是C,而不是C ++,因此也可以排除包含64位整数和重载-mtune=atom运算符的类。

我们可以排除FP类型,因为它会使用FP乘法。