本节进行一个综合实验:
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字节。
小结: