数据结构(struct
s、union
s、class
es 等)是在编译步骤发生后完全消失的更高级别的元素。这意味着概念本身在二进制中完全不可见。当然,某些代码模式可能仍然暗示或暗示代码中存在数据结构,没有与struct
,union
或class
关键字等效的程序集(也不需要)。
提供上述上下文后,我将解决您在整个问题中提出的具体问题和陈述:
我相信那ebp + offset
是局部变量?
您准确地理解ebp
用于引用堆栈,因此任何ebp
基于引用的引用都可能是对基于堆栈的变量的引用。
它真的只是大量的局部变量吗?
它可以。然而,正如我在第一段中所解释的那样,无法确定原始源代码是否有很多局部变量或单个、几个甚至嵌套结构。
但是,没有必要(除非您的目标是实现二进制相同的代码重构)专门使用原始代码中使用的相同结构。如果你的目标是对代码有一个很好的理解,你应该可以随意实现你认为合适的数据结构,这对你来说是最直观的表示。您应该依赖 IDA 的结构定义,使汇编代码对您尽可能具有可读性,而不必过多考虑原始源代码的编写方式。
或者它实际上是一种数据结构,这就是 IDA 表示它的方式?
因此,这不是“IDA 表示它”的方式,而是任何编译器将代码转换为汇编的方式。IDA 只是帮助提供反汇编机器代码的交互界面。
ebp
是结构的基地址
由于函数以一个相当标准的方式开始,mov ebp, esp / sub esp, IMM
它ebp
本身不太可能指向一个结构。它指向创建新堆栈帧的堆栈偏移量。这是一种非常普遍的做法。然而,一个结构很可能从堆栈上的某个偏移量开始,并ebp
使用从堆栈帧开始的偏移量来引用它。
的mov
所述指令之间mov [...], offset value
的填充字节
假设您在谈论mov, REG, IMM
指令,这些可能是进一步使用的寄存器初始化。mov
出于性能原因,它们分布在基于堆栈的指令之间。简单地说,流水线优化允许现代处理器在某种程度上与较慢的 RAM 写操作并行分配寄存器值,从而提高整体执行速度。
我猜它们只是填充字节,因为esi
不包含值(它xor
在屏幕截图的顶部)并且mov ebp + offset
在这个块中相当多。
该esi
寄存器确实包含一个值,该值只是零。xor
将寄存器与它自己一起是将其设置为零的常用方法,这比mov REG, 0
编码指令要短。此外,mov OFFSET, REG
比 短mov OFFSET, 0
,因此编译器总体上为我们节省了几个字节的代码。