问题描述
我试图扭转这个神秘功能。这个函数返回一个整数,并将一个struct节点作为参数
#includemystery.h
int mystery(struct e4_struct * s){}
头文件是一个简单的struct声明
struct my_struct {
int a;
int b;
};
我想要反向工程的程序集是
$ b $ (%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;
返回i;
}
但这是不正确的。我不明白什么 mov%eax,(%rdi)完全相同,并且函数返回的结果是因为它应该返回并且是整数。
由于 RDI 是指向结构开始的指针(函数的第一个参数)下面一行是获取 s-> a 的值并将其放入临时寄存器 EAX 中。
mov(%rdi),%eax
合理的可能是 int x = s-> a 。这一行:
lea(%rax,%rax,2),%eax
与从RAX + RAX * 2 = 3 * RAX(因此s-> a * 3)开始,将温度值乘以3相同。因此,前两行的程序集可以表示为:
int x = s-> a * 3;
行 mov%eax,(%rdi)将取临时值 x 并将其存储回s-> a以便可以表示为:
s-> a = x;
addl $ 0x7,0x4(%rdi)将4添加到7(RDI)。 4(RDI)是s-> b的地址。这条线可以表示为 s-> b + = 7; 。
一个值?由于在上面分析的代码之后没有其他的东西用于EAX ,所以EAX 仍然是我们前面做的 x = s-> gt时的值; a * 3; 。这意味着函数返回临时值 x 。然后代码如下所示: p>
int mystery(struct my_struct * s)
{
int x = s-> a * 3;
s-> a = x;
s-> b + = 7;
return x;
$
如果你在与我找到的 mystery 函数不同具有优化级别 -O1 的GCC 4.9.x生成了我正在寻找的确切代码。看起来,为这些神秘练习生成装配文件的人使用了这样的设置和类似的编译器。
I'm trying to reverse engineer this mystery function. This function returns an integer and takes a struct node as an argument
#include "mystery.h" int mystery(struct e4_struct *s){}The header file is a simple struct declaration
struct my_struct { int a; int b; };The assembly I'm trying to reverse engineer is
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 retqSo far I think the function is like:
int mystery(struct m_struct *s){ int i = s->a; i = 3*i; int j = s->b; j += 7; return i; }But this isn't correct. I don't understand what mov %eax,(%rdi)does exactly and what the function returns in the end because its supposed to return and integer.
解决方案Given that RDI is the pointer to the beginning of the structure (first parameter of function) the following line is getting the value of s->aand placing it in a temporary register EAX.
mov (%rdi),%eaxReasonably that might be int x = s->a. This line:
lea (%rax,%rax,2),%eaxIs the same as multiplying the temp value by 3 since RAX+RAX*2=3*RAX (thus s->a * 3). So the first two lines of assembly could be represented as:
int x = s->a * 3;The line mov %eax,(%rdi) would be taking the temporary value x and storing it back to s->a so that could be represented as:
s->a = x;The line addl $0x7,0x4(%rdi) is adding 7 to the value at 4(RDI). 4(RDI) is the address of s->b. This line could be represented as s->b += 7;.
So what is being returned as a value? Since nothing else is done with EAX after the code analyzed above, EAX is is still the value it had earlier when we did x = s->a * 3;. This means that the function is returning the temporary value x.
The code then would look like this:
int mystery(struct my_struct *s) { int x = s->a * 3; s->a = x; s->b += 7; return x; }If you compile this code with GCC 4.9.x on godbolt with -O1 optimization level we get this generated assembly:
mystery: movl (%rdi), %eax leal (%rax,%rax,2), %eax movl %eax, (%rdi) addl $7, 4(%rdi) retDifferent compilers with different optimizations levels will produce different assembly that will all do the same thing. GCC 4.9.x just so happens to produce the exact assembly code we originally reverse engineered.
Note: I guessed on the version of compiler and optimization level because of a recent SO question with a different mystery function where I had found GCC 4.9.x with optimization level -O1 generated the exact code I was looking for. It seems whoever generated the assembly files for these mystery exercises was using such settings and similar compiler.
这篇关于从给定的x86程序集编写一个C函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!