标签:src 联系 isa linux环境 链接 http ext 无法 函数调用
前言:
我们都知道我们所写的程序是被编译为一条条的CPU指令去执行的,但是在linux系统下能够运行的程序在windows环境下却运行不起来,但是我们使用的CPU明明是一样的,这又是为什么呢?
一、程序的执行:编译、链接和装载
程序示例1:
// add_lib.c int add(int a, int b) { return a+b; }
// link_example.c #include <stdio.h> int main() { int a = 10; int b = 5; int c = add(a, b); printf("c = %d\n", c); }
单独编译:
$ gcc -g -c add_lib.c link_example.c $ objdump -d -M intel -S add_lib.o $ objdump -d -M intel -S link_example.o
编译结果:
add_lib.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <add>: 0: 55 push rbp 1: 48 89 e5 mov rbp,rsp 4: 89 7d fc mov DWORD PTR [rbp-0x4],edi 7: 89 75 f8 mov DWORD PTR [rbp-0x8],esi a: 8b 55 fc mov edx,DWORD PTR [rbp-0x4] d: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8] 10: 01 d0 add eax,edx 12: 5d pop rbp 13: c3 ret
link_example.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main>: 0: 55 push rbp 1: 48 89 e5 mov rbp,rsp 4: 48 83 ec 10 sub rsp,0x10 8: c7 45 fc 0a 00 00 00 mov DWORD PTR [rbp-0x4],0xa f: c7 45 f8 05 00 00 00 mov DWORD PTR [rbp-0x8],0x5 16: 8b 55 f8 mov edx,DWORD PTR [rbp-0x8] 19: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] 1c: 89 d6 mov esi,edx 1e: 89 c7 mov edi,eax 20: b8 00 00 00 00 mov eax,0x0 25: e8 00 00 00 00 call 2a <main+0x2a> 2a: 89 45 f4 mov DWORD PTR [rbp-0xc],eax 2d: 8b 45 f4 mov eax,DWORD PTR [rbp-0xc] 30: 89 c6 mov esi,eax 32: 48 8d 3d 00 00 00 00 lea rdi,[rip+0x0] # 39 <main+0x39> 39: b8 00 00 00 00 mov eax,0x0 3e: e8 00 00 00 00 call 43 <main+0x43> 43: b8 00 00 00 00 mov eax,0x0 48: c9 leave 49: c3 ret
分析:实际上以上编译结果是无法运行的,下面来分析一下
gcc -o 命令进行链接:
$ gcc -o link-example add_lib.o link_example.o $ ./link_example c = 15
链接结果:
link_example: file format elf64-x86-64 Disassembly of section .init: ... Disassembly of section .plt: ... Disassembly of section .plt.got: ... Disassembly of section .text: ... 6b0: 55 push rbp 6b1: 48 89 e5 mov rbp,rsp 6b4: 89 7d fc mov DWORD PTR [rbp-0x4],edi 6b7: 89 75 f8 mov DWORD PTR [rbp-0x8],esi 6ba: 8b 55 fc mov edx,DWORD PTR [rbp-0x4] 6bd: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8] 6c0: 01 d0 add eax,edx 6c2: 5d pop rbp 6c3: c3 ret 00000000000006c4 <main>: 6c4: 55 push rbp 6c5: 48 89 e5 mov rbp,rsp 6c8: 48 83 ec 10 sub rsp,0x10 6cc: c7 45 fc 0a 00 00 00 mov DWORD PTR [rbp-0x4],0xa 6d3: c7 45 f8 05 00 00 00 mov DWORD PTR [rbp-0x8],0x5 6da: 8b 55 f8 mov edx,DWORD PTR [rbp-0x8] 6dd: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] 6e0: 89 d6 mov esi,edx 6e2: 89 c7 mov edi,eax 6e4: b8 00 00 00 00 mov eax,0x0 6e9: e8 c2 ff ff ff call 6b0 <add> 6ee: 89 45 f4 mov DWORD PTR [rbp-0xc],eax 6f1: 8b 45 f4 mov eax,DWORD PTR [rbp-0xc] 6f4: 89 c6 mov esi,eax 6f6: 48 8d 3d 97 00 00 00 lea rdi,[rip+0x97] # 794 <_IO_stdin_used+0x4> 6fd: b8 00 00 00 00 mov eax,0x0 702: e8 59 fe ff ff call 560 <printf@plt> 707: b8 00 00 00 00 mov eax,0x0 70c: c9 leave 70d: c3 ret 70e: 66 90 xchg ax,ax ... Disassembly of section .fini: ...
分析:
由c语言生成汇编码再到机器码执行的过程分两部分:
二、ELF文件结构
三、ELF文件链接过程
链接时,扫描所有目标文件,收集所有符号表,将所有符号表合并成一个符号表;
根据重定向表所有不确定的地址进行修正;
将代码段进行合并,生成一个可执行文件;
总结:
讲了这么多,为什么linux环境下的可执行文件和windows环境下的不同呢?这是因为两种环境下运行的可执行文件的文件格式是不一样的,而想要在linux环境运行windows环境的可执行文件,需要通过一种能够兼容ELF格式文件的装载器。
扩展:这里可以联系java的类装载机制,class被加载到方法区才能运行,其实jvm内的方法区就是一个大的.text Section,全局的。
标签:src 联系 isa linux环境 链接 http ext 无法 函数调用
原文地址:https://www.cnblogs.com/rxmind/p/12801249.html