揭开连接器的面纱(下)

本节进行一个综合实验:

write函数也属于libc库,write不是系统调用,只是系统调用的一个封装。

 打印函数直接使用sys_write这个系统调用。系统调用编号为4。

 退出函数直接使用sys_exit这个系统调用。系统调用编号为1。

链接脚本:

 代码段的起始地址在0x08048000的基础上加上一个文件头的偏移。

代码段和只读数据段都放入text段中。rodata合并进入text后仍然具有只读属性。

合并段就达到了减少段的目的。

DISCARD声明可以删除其他段。

 ld默认情况下是动态链接的。静态链接需要指定参数。

program.c如下:

 1 void print(const char* s, int l);
 2 void exit(int code);
 3 
 4 void program()
 5 {
 6     print("D.T.Software\n", 13);
 7     exit(0);
 8 }
 9 
10 void print(const char* s, int l)
11 {
12     asm volatile (
13         "movl $4, %%eax\n"
14         "movl $1, %%ebx\n"
15         "movl %0, %%ecx\n"
16         "movl %1, %%edx\n"
17         "int $0x80     \n"
18         :
19         : "r"(s), "r"(l)
20         : "eax", "ebx", "ecx", "edx"
21     );
22 }
23 
24 void exit(int code)
25 {
26     asm volatile (
27         "movl $1, %%eax\n"
28         "movl %0, %%ebx\n"
29         "int $0x80     \n"
30         :
31         : "r"(code)
32         : "eax", "ebx"
33     );
34 }

编译检查:

makefile如下:

 1 CC := gcc
 2 LD := ld
 3 RM := rm -fr
 4 
 5 TARGET := program.out
 6 SRC := $(TARGET:.out=.c)
 7 OBJ := $(TARGET:.out=.o)
 8 LDS := $(TARGET:.out=.lds)
 9 
10 .PHONY : rebuild clean all
11 
12 $(TARGET) : $(OBJ) $(LDS)
13     $(LD) -static -T $(LDS) -o $@ $<
14     @echo "Target File ==> $@"
15     
16 $(OBJ) : $(SRC)
17     $(CC) -fno-builtin -o $@ -c $^
18     
19 rebuild : clean all
20 
21 all : $(TARGET)
22 
23 clean :
24     $(RM) $(TARGET) $(OBJ)
25     
26     

链接脚本如下:

 1 ENTRY(program)
 2 
 3 SECTIONS
 4 {
 5     .text 0x08048000 + SIZEOF_HEADERS :
 6     {
 7         *(.text)
 8         *(.rodata)
 9     }
10     
11     /DISCARD/ :
12     {
13         *(*)
14     }
15 }

 结果:

 生成的可执行程序的大小为582字节。

小结:

猜你喜欢

转载自www.cnblogs.com/wanmeishenghuo/p/9827056.html
今日推荐