在使用结构时,如何将以下汇编代码从编译器转换为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
(typeint**
)指定给ss->next
(typestruct 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和指针的经验。