根据最近由MSVC编译的“ HelloWorld.exe”的说法:

.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都使用它们进行线程本地存储,但是这些指令在指令中始终具有显式的前缀字节。