最近在看《程序员的自我修养-链接、装载与库》,在学习使用链接脚本的时候碰到点问题,特此记录,以便日后回顾,总结!
char * str = "Hello world!\n"; void print(void) { asm("movl $13,%%edx \n" "movl %0,%%ecx \n" "movl $0,%%ebx \n" "movl $4,%%eax \n" "int $0x80 \n" ::"r"(str):"edx","ecx","ebx"); } void exit(void) { asm("movl $42,%ebx \n" "movl $1, %eax \n" "int $0x80 \n"); } void nomain(void) { print(); exit(); }
编译环境: 64bit ubuntu 12.04 LTS
第1步: 生成目标文件
tzw@tzw-ubuntu:~/temp$ gcc -c -fno-builtin TinyHelloWorld.c
出现如下错误:
TinyHelloWorld.c: Assembler messages:
TinyHelloWorld.c:6: Error: unsupported for `mov'
google了一下,发现是因为在64位机器上编译32位的汇编码导致的。解决方法就是加个-m32的选
项,使gcc使用32位的ABI
tzw@tzw-ubuntu:~/temp$ gcc -m32 -c -fno-builtin TinyHelloWorld.c
成功生成目标文件!
gcc选项说明
----------------------------------------------------------------------------------------------------------------------------
-c 只编译汇编成目标文件不链接
-fno-builtin 关闭gcc内置函数功能
关于内置函数
----------------------------------------------------------------------------------------------------------------------------
gcc编译器提供了很多内置函数(Built-in Function),它会把一些常用的C库函数替换成编译器的
内置函数,以达到优化的功能。比如gcc会将只有字符串参数的printf函数替换成puts,以节省格式
解析的时间
第2步 链接生成可执行文件
tzw@tzw-ubuntu:~/temp$ ld -static -e nomain -o TinyHelloWorld TinyHelloWorld.o
很不幸又没成功:-( 出现如下错误提示
ld: i386 architecture of input file `TinyHelloWorld.o' is incompatible with i386:x86-64 outputld:
原来刚才编译的过程中生成了elf_i386格式的目标文件,由于系统是64bit的,默认情况下输入文件
格式为elf_x86_64,这就导致了实际输入文件格式与期待的输入文件格式不匹配(唉!学习的话还
是装32bit系统好啊)
最后还是借助万能的google找到了解决方法,链接命令如下
tzw@tzw-ubuntu:~/temp$ ld -m elf_i386 -static -e nomain -o TinyHelloWorld TinyHelloWorld.o
ld选项说明
----------------------------------------------------------------------------------------------------------------------------
-static 让链接器使用静态链接的方式进行链接
-e 指定程序入口函数
-m 设置输入文件格式
-o 指定输出文件的文件名