最近在看《程序员的自我修养-链接、装载与库》,在学习使用链接脚本的时候碰到点问题,特此记录,以便日后回顾,总结!


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 指定输出文件的文件名