想象一下我有以下代码
void A(){
// blah blah blah
}
void B(){
// blah blah blah
}
void C(){
// blah blah blah
}
当代码编译(使用Visual Studio)并加载到内存中执行时,A()、B()、C()的地址可能不按顺序排列。我们怎样才能让他们订购?在这种情况下是否有任何指令有用?
想象一下我有以下代码
void A(){
// blah blah blah
}
void B(){
// blah blah blah
}
void C(){
// blah blah blah
}
当代码编译(使用Visual Studio)并加载到内存中执行时,A()、B()、C()的地址可能不按顺序排列。我们怎样才能让他们订购?在这种情况下是否有任何指令有用?
如果您的程序由单个翻译单元(源文件)组成,则生成的二进制文件通常应按照在翻译单元中定义的顺序包含函数。例如,考虑以下程序:
int A() { return 0; }
int B() { return 1; }
int C() { return -1; }
int main() { return A() + B() + C(); }
如果你编译这个针对最小尺寸优化的程序 (/O1) 并禁用内联函数扩展 (/Ob0),将生成以下机器代码:
int A() { return 0; }
00F71000 33 C0 xor eax,eax
00F71002 C3 ret
int B() { return 1; }
00F71003 33 C0 xor eax,eax
00F71005 40 inc eax
00F71006 C3 ret
int C() { return -1; }
00F71007 83 C8 FF or eax,0FFFFFFFFh
00F7100A C3 ret
int main() { return A() + B() + C(); }
00F7100B E8 F0 FF FF FF call A (0F71000h)
00F71010 8B C8 mov ecx,eax
00F71012 E8 EC FF FF FF call B (0F71003h)
00F71017 03 C8 add ecx,eax
00F71019 E8 E9 FF FF FF call C (0F71007h)
00F7101E 03 C1 add eax,ecx
00F71020 C3 ret
源注释由调试器提供。当使用其他优化设置时,需要对最小尺寸进行优化以消除int 3
放置在函数之间的填充。必须禁用内联函数扩展以确保函数实际存在于生成的二进制文件中。
据我所知,这是一个实现细节,因此不应在生产代码中依赖它。
如果您确实将它们拆分为单独的函数只是为了便于阅读,并且您在整个程序中只调用它们一次 - 内联声明这些函数,因此编译器会将它们组合成一段代码而无需任何调用指令。
否则没有理由将它们按顺序放置在内存中,因为任何调用指令都会刷新 CPU 的流水线。