.text:00411279 call ds:__imp__printf
所以,为什么基地址是数据段,而不是代码段(这将是更多)逻辑上要做的事情?)
项目使用多线程Debug Dll作为运行时库。
#1 楼
Windows没有这么做;
__imp__printf
处的内容不是函数的代码;它是函数代码的指针。由于它是一个指针(它是数据,而不是代码),因此将指针值放在数据段中而不在代码段中是有意义的。更具体地说,此指针值是由加载程序在运行时设置的,因此内存页需要是可写的,这更多的原因是此页位于数据段而不是代码段中。 > #2 楼
ds:
是由IDA而不是由编译器添加的。如果查看原始操作码字节,则会看到指令中没有DS覆盖前缀。这样做很傻。IDA添加了
ds:
前缀,因为否则您将不知道这是一个间接调用-也就是说,它正在读取一个名为32位地址的变量然后调用存储在该变量中的地址。如果没有__imp__printf
,它将直接直接调用ds:
。如果IDA使用更好的汇编语言语法(即nasm语法),则该指令看起来像这样,用方括号显示它是一个内存读取(和
__imp__printf
区别于dword
的其他几种怪异类型):.text:00411279 call dword [__imp__printf]
Windows,几乎与其他所有32位OS一样,具有平坦的地址空间。 CS,DS,ES和SS都具有相同的基址,即0,因此使用哪个段作为基址无关紧要。 (除非CS是您的段,否则您不能进行内存写入。)FS和GS具有不同的基础,因为主要的OS都使用它们进行线程本地存储,但是这些指令在指令中始终具有显式的前缀字节。