我正在尝试对这个神秘函数进行逆向工程。 该函数返回一个整数并以一个结构节点作为参数
#include "mystery.h"
int mystery(struct e4_struct *s){}
头文件是一个简单的结构声明
struct my_struct {
int a;
int b;
};
我要逆向工程的程序集是
400596: 8b 07 mov (%rdi),%eax
400598: 8d 04 40 lea (%rax,%rax,2),%eax
40059b: 89 07 mov %eax,(%rdi)
40059d: 83 47 04 07 addl $0x7,0x4(%rdi)
4005a1: c3 retq
到目前为止我认为函数是这样的:
int mystery(struct m_struct *s){
int i = s->a;
i = 3*i;
int j = s->b;
j += 7;
return i;
}
但这是不正确的。我不明白 mov %eax,(%rdi)
到底做了什么以及函数最终返回了什么,因为它应该返回整数。
最佳答案
鉴于 RDI 是指向结构开头的指针(函数的第一个参数),下面一行获取 s->a
的值并将其放置在临时寄存器 EAX 中。
mov (%rdi),%eax
按理说这可能是 int x = s->a
。这一行:
lea (%rax,%rax,2),%eax
与将温度值乘以 3 相同,因为 RAX+RAX*2=3*RAX(因此 s->a * 3)。因此前两行汇编可以表示为:
int x = s->a * 3;
行 mov %eax,(%rdi)
将采用临时值 x
并将其存储回 s->a 以便可以表示为:
s->a = x;
addl $0x7,0x4(%rdi)
行将 4(RDI) 处的值加 7。 4(RDI)是s->b的地址。此行可以表示为 s->b += 7;
。
那么返回的值是什么?由于在上面分析的代码之后没有对 EAX 做任何其他事情,EAX 仍然是我们之前执行 x = s->a * 3 时的值;
。这意味着该函数正在返回临时值 x
。
代码看起来像这样:
int mystery(struct my_struct *s)
{
int x = s->a * 3;
s->a = x;
s->b += 7;
return x;
}
如果您在 godbolt 上使用 GCC 4.9.x 编译此代码使用 -O1
优化级别,我们得到了这个生成的程序集:
mystery:
movl (%rdi), %eax
leal (%rax,%rax,2), %eax
movl %eax, (%rdi)
addl $7, 4(%rdi)
ret
具有不同优化级别的不同编译器将生成不同的程序集,这些程序集都将执行相同的操作。 GCC 4.9.x 恰好生成了我们最初逆向工程的精确汇编代码。
注意:由于最近的 SO question,我猜测了编译器的版本和优化级别具有不同的 mystery
功能,我发现 GCC 4.9.x 具有优化级别 -O1
生成了我正在寻找的确切代码。似乎为这些神秘 练习生成汇编文件的人正在使用这样的设置和类似的编译器。
关于c - 从给定的 x86 程序集编写 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49350723/