在使用结构时,如何将以下汇编代码从编译器转换为C?

在使用结构时,如何将以下汇编代码从编译器转换为C?,c,pointers,assembly,struct,x86-64,C,Pointers,Assembly,Struct,X86 64,假设我定义了一个新的结构: struct s { int *x; struct { short sh[2]; int i; } w; struct s *next; }; 此外,我还编写了一个函数来初始化它: void init_s(struct s *ss) { ss->w.sh[1] = /* Line 1 */; ss->x = /* Line 2 */; ss->next = /* Line 3 */;

假设我定义了一个新的
结构

struct s {
   int *x;
   struct {
      short sh[2];
      int i;
   } w;
   struct s *next;
};
此外,我还编写了一个函数来初始化它:

void init_s(struct s *ss) {
   ss->w.sh[1] = /* Line 1 */;
   ss->x = /* Line 2 */;
   ss->next = /* Line 3 */;
}
编译器为
init\u s
生成以下汇编代码:

init_s:             # line 1
   movw 8(%rdi), %ax    # line 2
   movw %ax, 10(%rdi)   # line 3
   leaq 12(%rdi), %rax  # line 4
   movq %rax, (%rdi)    # line 5
   movq %rdi, 16(%rdi)  # line 6
   retq                 # line 7
我试图做的是根据程序集为
init\u s
填充缺少的代码行。我已经弄明白了(或者至少我认为是这样)第1行和第2行。第1行应该是
ss->w.sh[0]
,第2行应该是
&(ss->w.sh[2])
。但是,我对3号线有问题。我想这应该是基于汇编的
&(ss->x)
,但我觉得这是不正确的,我不知道为什么。如果有任何反馈或建议能帮助我更多地了解汇编和结构,我们将不胜感激

第1行应该是
ss->w.sh[0]

我同意

第2行应该是
&(ss->w.sh[2])

这是正确的地址,除了
ss->w.sh
只有2个元素,因此
w.sh[2]
是不允许的。这是指向结构的下一个成员的指针,即
ss->x=&(ss->w.i)
。这对于
ss->x
成员是
int*
而不是
short*
也是有意义的

但是,我对3号线有问题。我想它应该是基于组件的
&(ss->x)

类似的问题:确实,
%rdi
可以是指向
ss->x
的指针,但是将
&ss->x
(type
int**
)指定给
ss->next
(type
struct s*
)没有意义。您还可以将
%rdi
视为指向结构
*ss
本身的指针,这更合理:
ss->next=ss。它生成一个循环链表,其中有一个节点的
下一个
就是它自己

这里的寓意是,在C中可以有不同的方式引用同一个地址,所有这些方式都将生成相同的程序集,并且您必须使用常识进行有根据的猜测,以确定作者更可能使用哪一种。理论上,C代码的作者可能编写了
ss->next=(struct s*)&(ss->x)作为第三行-我们不能证明他们没有-但是
ss->next=ss
更合理,因此可能性更大


这就是为什么逆向工程既是一门科学又是一门艺术。

虽然我知道你的
init\u s
是一个带有占位符的例子,也许你还应该展示你用来生成程序集的实际编译代码?@AKX:我想这个想法是逆向工程
init\u s
。你说得对。我不知道第一部分是假设的。谢谢你澄清你的推理。现在把它看作一个链表就更有意义了。当我写我的问题时,我也没有意识到w.sh的指数超出了范围。结构对我来说只是有点奇怪,因为我直到最近才有使用C和指针的经验。