学习C编译过程:汇编器如何分配内存及确定外部函数跳转地址?
关于C编译中汇编阶段对未定义外部函数的处理
先看你给出的代码:
int add(int a, int b); int main(){ int tmp = add(1,2); return 0; }
针对你的问题,逐个说明:
汇编器不需要知晓
add函数的实际地址
汇编阶段处理调用add的代码时,会用符号引用代替真实地址。比如x86架构下会生成call add这样的汇编指令,汇编器会把add标记为未解析的外部符号,并记录到目标文件(.o)的符号表中。它不需要知道add在哪,只需要标记出“这里有个外部符号,后面要处理”。汇编阶段的核心操作
汇编器的工作是把汇编代码翻译成机器码,同时维护两个关键表:- 符号表:记录当前目标文件里定义的符号(比如
main)和引用的外部符号(比如add); - 重定位表:标记哪些机器指令里的地址是占位符,需要在链接阶段被替换成真实地址。比如
call add对应的机器码里会有一个临时地址值,重定位表会告诉链接器“这个位置要替换成add的实际地址”。
- 符号表:记录当前目标文件里定义的符号(比如
不会为
add函数预留内存
目标文件的text段里只有main函数的代码,add函数的定义根本不在当前编译单元里,所以汇编器不会为它分配任何内存空间。内存分配和地址确定都是链接阶段的事:链接器会找到包含add定义的目标文件/库,把add的代码合并到最终可执行文件的text段,然后根据add的实际位置,修正main里call指令的地址。
另外补充:你提到的“不知道add函数的长度”其实不影响汇编阶段的工作——函数调用指令只关心目标地址,和函数本身的长度没有关系;函数长度是链接时合并段才需要考虑的,但那是链接器的职责,和汇编器无关。
内容的提问来源于stack exchange,提问作者Erinç Utku Öztürk
相关产品推荐
相关产品推荐

