《一个操作系统的实现》(五):1.ELF

来源:互联网 发布:mysql order by count 编辑:程序博客网 时间:2024/05/29 19:02

首先展示一段汇编的“Hello, world!”的代码:

hello.asm

[section .data];数据在此strHellodb"Hello, world!", 0AhSTRLENequ$ - strHello[section .text];代码在此global _start;必须导出_start这个入口以便链接器识别_start:movedx, STRLENmovecx, strHellomovebx, 1moveax, 4;sys_writeint0x80;系统调用movebx, 0moveax, 1;sys_exitint0x80;系统调用

用nasm编译:nasm -f elf hello.asm -o hello.o

其中-f elf指定输出文件格式为ELF格式

ld -s hello.o -o hello

其中-s可以去掉符号表等内容,可缩减生成的可执行代码

执行:./hello

输出Hello, world!

下面是汇编和C代码一块儿用的

foo.asm

extern choose;int choose(int a, int b);[section .data];数据在此num1stdd3num2nddd4[section .text];代码在此global _start;导出_start入口,以便让链接器识别global myprint;导出这个函数为了让bar.c使用_start:pushdword [num2nd]pushdword [num1st]callchoose;choose(num1st, num2nd);addesp, 8movebx, 0moveax, 1;sys_exitint0x80;系统调用;void myprint(char* msg, int len)myprint:movedx, [esp+8];lenmovecx, [esp+4];msgmovebx, 1mov eax, 4;sys_writeint0x80;系统调用ret

bar.c

void myPrint(char * msg, int len);int choose(int a, int b){if(a >= b) {myprint("the first one\n", 13);}else {myprint("the second one\n", 13);}return 0;}

编译和执行过程:

nasm -f elf -o foo.o foo.asm

gcc -c -o bar.o bar.c

ld -s -o foobar foo.o bar.o

./foobar

因为在bar.c中使用了foo.asm中的函数myprint,所以要用global导出。而foo.asm中调用了bar.c中的choose函数,所以要用extern声明。而且在参数入栈的时候,遵循C调用约定,后一个参数先入栈,并由调用者清理堆栈。


下面是ELF的内容——

ELF文件由4部分组成,分别是ELF头、程序头表、节、节头表。不过一个文件中不一定包含全部这些内容,而且只有ELF头的位置是固定的,其余各部分的位置、大小等信息由ELF头中的各项值来决定。ELF格式的详解见这篇文章,内容比较多...

ELF定义了一些数据类型(Elf32_Word、Elf32_Sword等),让文件格式与机器无关。(ELF文件力求支持从8位到32位不同架构的处理器)

程序头描述的是一个段在文件中的位置、大小以及它被放进内存后所在的位置和大小。这些信息正是我们想把一个文件加载进内存的重要信息。


这是第五章前三节的东西,内容比较少,后两节内容多一些