奇怪的是,位置 096B3D47 只是上面摘录的几行......
...并且该地址之前的指令是一条call指令。对?
这种指令用于与位置无关的代码:该代码可以加载到另一个地址中,并且无需修改即可以相同的方式工作。通常它是这样工作的:
call some_address ; 1
some_address:
pop ebx ; 2
lea eax, (some_text - some_address)[ebx] ; 3
...
some_text:
...
- 在
call指令之后,指令之后的指令地址call将被压入堆栈。这意味着地址some_address现在在堆栈上。
- 使用
pop我们some_address从堆栈中读取的地址(并从那里删除它)。
- 此指令将进行计算,
some_text - some_address + someaddress因此该指令与 具有相同的效果lea eax, [some_text]。
some_text - some_address当可执行文件加载到不同的内存地址时,距离总是相同的。因此,lea指令将在执行程序的位置(地址)上独立工作。
call指令也是如此,因为指令的参数call是相对于 PC 存储的。
lea eax, [some_text]然而,指令的参数将是一个绝对(不是 PC 相关的)地址,因此在另一个地址执行程序时必须交换它。
对我来说,它读起来像“符号表索引之前 0x96B3D47 字节处的符号”。
如果lea指令有重定位表条目,反汇编器可以从重定位表中获取信息。
在您的情况下,这似乎有所不同:
您的反汇编程序似乎也足够智能,可以看到此时ebx包含地址 096B3D47。因此,就知道该指令lea eax, XYZ[ebx]将导致一个值096B3D47+XYZ的eax寄存器。
因此,它会将指令反汇编为lea eax, ((XYZ+096B3D47)-096B3D47)[ebx]并尝试找出地址XYZ+096B3D47是什么符号。
然而,我知道的许多反汇编程序只是在这里猜测;他们假设地址属于该地址之前的最后一个符号。在你的情况下,符号stru_8199A2C.st_shndx似乎就是那个符号。
显然,您的反汇编器不仅会评估符号,还会评估调试信息,例如“Dwarf”调试数据(其中包含调试器使用的信息)。