哈工大计算机系统2022大作业:程序人生-Hello‘s P2P
计算机系统
大作业
题 目 程序人生-Hello’s P2P
专 业 计算机类
学 号 120L022115
班 级 2003007
学 生 王炳轩
指 导 教 师 吴锐
计算机科学与技术学院
2021年5月
关键词:计算机系统;预处理;编译;汇编;链接;内存;CPU;
6.2 简述壳Shell-bash的作用与处理流程... - 27 -
6.3 Hello的fork进程创建过程... - 27 -
7.2 Intel逻辑地址到线性地址的变换-段式管理... - 32 -
7.3 Hello的线性地址到物理地址的变换-页式管理... - 33 -
7.4 TLB与四级页表支持下的VA到PA的变换... - 34 -
7.5 三级Cache支持下的物理内存访问... - 36 -
7.6 hello进程fork时的内存映射... - 37 -
7.7 hello进程execve时的内存映射... - 37 -
第1章 概述
1.1 Hello简介
根据Hello的自白,利用计算机系统的术语,简述Hello的P2P,020的整个过程。
在Linux系统中,程序(Program)源代码hello.c经过预处理(cpp)、编译(ccl)、汇编(as)、链接(ld)最终输出可执行目标程序hello。
在shell(Terminal bash)中输入命令行./hello后,shell调用OS(进程管理)函数fork(),配合execve(),产生了hello的相应(子)进程(Process)。
1.2 环境与工具
列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。
硬件环境:Surface Go 3(x86-64、Intel Pentium G6500-Y @1.1GHz、8GB DRAM、128GB SSD)
软件环境:Windows 11、Windows Subsystem for Linux、Ubuntu 20.04
开发调试工具:Virtual Studio 2019、Dev C++、Code::Blocks、gcc、gdb、edb、objdump、vi/vim、as、ld、readelf、winHex
1.3 中间结果
列出你为编写本论文,生成的中间结果文件的名字,文件的作用等。
文件名 |
作用 |
hello.c |
程序源代码 |
hello.i |
hello.c经预处理之后得到的程序文件 |
hello.s |
hello.i文件经编译后得到的汇编语言源代码文件 |
hello.o |
hello.s文件经汇编后得到的可重定位目标文件 |
hello |
hello.o文件经过链接后得到的可执行目标文件 |
hello.o.objdump.txt |
hello.o的反汇编代码 |
hello.objdump.txt |
hello的反汇编代码 |
1.4 本章小结
本章主要介绍了hello程序的P2P,020过程,以及进行实验时的软硬件环境、开发与调试工具和在本论文中生成的中间结果文件。
第2章 预处理
2.1 预处理的概念与作用
通过预处理生成的预处理文件(hello.i)是一个可读但不包含任何宏定义的文件。预处理的具体作用表现为:
2. 插入头文件到“#include”处,可以递归方式进行处理。
3. 处理所有条件包含指令,如“#if”、“#ifdef”、“#endif”等。
4. 添加行号和文件名标识,以便编译器产生调试用的行号信息。
2.2在Ubuntu下预处理的命令
gcc -E hello.c -o hello.i 或 cpp hello.c > hello.i
2.3 Hello的预处理结果解析
2.4 本章小结
本章介绍了预处理的概念及作用、通过运行命令展示预处理的结果并进行解析。
第3章 编译
3.1 编译的概念与作用
2. 语法分析器,将词法分析得到的标记流(token)生成一棵语法树。
把预处理完的程序代码进行一系列词法分析、语法分析、语义分析及优化后生成相应的汇编代码文件。例如,编译器(ccl)将hello.i翻译成一个汇编语言程序hello.s。
3.2 在Ubuntu下编译的命令
3.3 Hello的编译结果解析
将hello.c翻译为hello.s,按C语句逐行对应如下表。其中使用【】包裹的语句为该行复杂语句的子语句。
汇编代码 |
C代码 |
.LC0: .string "\347\224\250\346\263\225: Hello \345\255\246\345\217\267 \345\247\223\345\220\215 \347\247\222\346\225\260\357\274\201" |
char** LC0="用法: Hello 学号 姓名 秒数!\n" |
.LC1: .string "Hello %s %s\n" |
char** LC1="Hello %s %s\n" |
main: .LFB6: .cfi_startproc endbr64 pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $32, %rsp movl %edi, -20(%rbp) movq %rsi, -32(%rbp) |
int main(int argc,char *argv[]){ int i; 【argc】 【argv[]】 |
cmpl $4, -20(%rbp) je .L2 |
if(argc!=4){ |
leaq .LC0(%rip), %rdi call puts@PLT |
printf("用法: Hello 学号 姓名 秒数!\n"); |
movl $1, %edi call exit@PLT |
exit(1); } |
.L2: movl $0, -4(%rbp) jmp .L3 .L3: cmpl $7, -4(%rbp) jle .L4 .L4: ……… addl $1, -4(%rbp) |
【i=0;】 【i<=7;】 for(i=0;i<8;i++){ .L4 } 【i++】 |
.L4: movq -32(%rbp), %rax addq $16, %rax movq (%rax), %rdx movq -32(%rbp), %rax addq $8, %rax movq (%rax), %rax movq %rax, %rsi leaq .LC1(%rip), %rdi movl $0, %eax call printf@PLT |
【argv[2]】 【argv[1]】 【”Hello %s %s”】 printf("Hello %s %s\n", |
movq -32(%rbp), %rax addq $24, %rax movq (%rax), %rax movq %rax, %rdi call atoi@PLT movl %eax, %edi call sleep@PLT |
【argv[3]】 【atoi(argv[3])】 sleep(atoi(argv[3])); |
.L3: call getchar@PLT |
getchar(); |
movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc |
return 0; |
3.4 本章小结
本章主要介绍了编译器将修改后的源文件hello.i翻译成为二进制文件hello.s的过程,并按hello.c的C代码逐行进行汇编代码的比对分析。
第4章 汇编
4.1 汇编的概念与作用
汇编是指将汇编语言书写的程序翻译成为与之等价的机器语言程序的过程。汇编器将hello.s翻译成机器语言指令,然后把这些指令打包成可重定位目标程序的格式,并将结果输出为可重定位目标文件hello.o。
汇编器(as)将hello.s 翻译成CPU语言指令,把这些指令打包成可重定位目标程序的格式,并且将结果保存在二进制目标文件hello.o当中。
4.2 在Ubuntu下汇编的命令
gcc -c hello.s -o hello.o 或 as hello.s -o hello.o
4.3 可重定位目标elf格式
分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特别是重定位项目分析。
包含字大小、字节顺序、文件类型(.o,exec,.so),机器类型等。
1) Magic:魔数,指名该文件是一个ELF目标文件。第一个字节7F是个固定的数;后面的3个字节为E,L,F三个字母的ASCII形式。
3) Data :文件中的数据是按照什么格式组织(大端或小端)的,不同处理器平台数据组织格式可能就不同,如x86平台为小端存储格式。
5) OS/ABI:指出操作系统类型,ABI 是 Application Binary Interface 的缩写。
10) 入口点地址:程序的虚拟地址入口点,因为这还不是可运行的程序,故而这里为零
11) 程序头起点:与上同理,这个目标文件没有 Program Headers。
13) 标志:是一个与处理器相关联的标志,x86平台上该处为0。
15) 程序头大小:因为这个不是可执行程序,故此处大小为 0。
16) Number ofprogram headera:与上同理。
17) 节头大小:这里每个 section 头大小为 64个字节。
18) 节头数量:一共有多少个 section 头,这里是13个。
19) 字符串表索引节头:section头字符串表索引号,此处保存着各个sections的名字,如.data,.text,.bss等。
一个符号表,它存放在程序中定义和引用的函数和全局变量的信息。
4.4 Hello.o的结果解析
objdump -d -r hello.o 分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。
说明机器语言的构成,与汇编语言的映射关系。特别是机器语言中的操作数与汇编语言不一致,特别是分支转移函数调用等。
操作数:机器语言反汇编后是十六进制的,而汇编语言中是十进制的。
C代码 |
|
.o反汇编代码 |
汇编代码 |
int main(int argc,char *argv[]){ int i; |
|
0000000000000000 <main>: 0: f3 0f 1e fa endbr64 4: 55 push %rbp 5: 48 89 e5 mov %rsp,%rbp 8: 48 83 ec 20 sub $0x20,%rsp c: 89 7d ec mov %edi,-0x14(%rbp) f: 48 89 75 e0 mov %rsi,-0x20(%rbp) |
main: .LFB6: .cfi_startproc endbr64 pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $32, %rsp movl %edi, -20(%rbp) movq %rsi, -32(%rbp) |
if(argc!=4){ |
|
13: 83 7d ec 04 cmpl $0x4,-0x14(%rbp) 17: 74 16 je 2f <main+0x2f> |
cmpl $4, -20(%rbp) je .L2 |
printf("用法: Hello 学号 姓名 秒数!\n"); |
|
19: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 20 <main+0x20> 1c: R_X86_64_PC32 .rodata-0x4 20: e8 00 00 00 00 callq 25 <main+0x25> 21: R_X86_64_PLT32 puts-0x4 |
leaq .LC0(%rip), %rdi call puts@PLT |
exit(1); } |
|
25: bf 01 00 00 00 mov $0x1,%edi 2a: e8 00 00 00 00 callq 2f <main+0x2f> 2b: R_X86_64_PLT32 exit-0x4 |
movl $1, %edi call exit@PLT |
for(i=0;i<8;i++){….} |
|
2f: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) 36: eb 48 jmp 80 <main+0x80> …… 7c: 83 45 fc 01 addl $0x1,-0x4(%rbp) 80: 83 7d fc 07 cmpl $0x7,-0x4(%rbp) 84: 7e b2 jle 38 <main+0x38> |
.L2: movl $0, -4(%rbp) jmp .L3 .L4: ……… addl $1, -4(%rbp) .L3: cmpl $7, -4(%rbp) jle .L4 |
printf("Hello %s %s\n",argv[1],argv[2]); |
|
38: 48 8b 45 e0 mov -0x20(%rbp),%rax 3c: 48 83 c0 10 add $0x10,%rax 40: 48 8b 10 mov (%rax),%rdx 43: 48 8b 45 e0 mov -0x20(%rbp),%rax 47: 48 83 c0 08 add $0x8,%rax 4b: 48 8b 00 mov (%rax),%rax 4e: 48 89 c6 mov %rax,%rsi 51: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 58 <main+0x58> 54: R_X86_64_PC32 .rodata+0x22 58: b8 00 00 00 00 mov $0x0,%eax 5d: e8 00 00 00 00 callq 62 <main+0x62> 5e: R_X86_64_PLT32 printf-0x4 |
movq -32(%rbp), %rax addq $16, %rax movq (%rax), %rdx movq -32(%rbp), %rax addq $8, %rax movq (%rax), %rax movq %rax, %rsi leaq .LC1(%rip), %rdi movl $0, %eax call printf@PLT |
sleep(atoi(argv[3])); |
|
62: 48 8b 45 e0 mov -0x20(%rbp),%rax 66: 48 83 c0 18 add $0x18,%rax 6a: 48 8b 00 mov (%rax),%rax 6d: 48 89 c7 mov %rax,%rdi 70: e8 00 00 00 00 callq 75 <main+0x75> 71: R_X86_64_PLT32 atoi-0x4 75: 89 c7 mov %eax,%edi 77: e8 00 00 00 00 callq 7c <main+0x7c> 78: R_X86_64_PLT32 sleep-0x4 |
movq -32(%rbp), %rax addq $24, %rax movq (%rax), %rax movq %rax, %rdi call atoi@PLT movl %eax, %edi call sleep@PLT |
getchar(); |
|
86: e8 00 00 00 00 callq 8b <main+0x8b> 87: R_X86_64_PLT32 getchar-0x4 |
call getchar@PLT |
return 0; } |
|
8b: b8 00 00 00 00 mov $0x0,%eax 90: c9 leaveq 91: c3 retq |
movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc |
4.5 本章小结
第5章 链接
5.1 链接的概念与作用
5.1.1 链接的概念
链接是指将可重定位目标文件经符号解析和重定位步骤合并成可执行目标文件,这个文件可被加载到内存并执行。
5.1.2 链接的作用
使得一个项目可以被分解成许多小模块,每个模块可单独进行修改、更新,最后通过链接形成一个项目时,减少不必要的操作。
5.2 在Ubuntu下链接的命令
5.3 可执行目标文件hello的格式
分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地址,大小等信息。
各段的入口地址、大小等基本信息如图所示。值得注意的是,入口地址与.o不同,不是从0开始了,是虚拟地址空间的地址,都是0x40xxxx。
5.4 hello的虚拟地址空间
使用edb加载hello,查看本进程的虚拟地址空间各段信息,并与5.3对照分析说明。
Edb中显示的相关信息内容段的地址与elfheader中标识的起始地址、大小相同。
5.5 链接的重定位过程分析
objdump -d -r hello 分析hello与hello.o的不同,说明链接的过程。
结合hello.o的重定位项目,分析hello中对其怎么重定位的。
下表展示了objdump hello.o与hello.out的不同处。
Hello.o |
Hello.out |
未包含外部库函数代码: 调用的外部库函数使用函数名@PLT并且有额外的信息存储目标函数的地址,但实际并未在文件中,仅仅是一个引用符号。 |
包含了外部库函数代码: 有了新的init、plt、plt.sec、fini段。 其中plt.sec是hello.c调用的库函数的代码,主函数中调用库函数的跳转也变成了虚拟相对地址。 |
指令地址从0开始。 |
指令地址都被转换为虚拟内存空间地址,从0x400000开始。 |
5.6 hello的执行流程
使用edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程。请列出其调用与跳转的各个子程序名或程序地址。
5.7 Hello的动态链接分析
分析hello程序的动态链接项目,通过edb调试,分析在dl_init前后,这些项目的内容变化。要截图标识说明。
动态链接的基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。
延迟绑定通过GOT和PLT实现,将过程地址的绑定推迟到下一次调用该过程时。
PLT:PLT是一个数组,其中每个条目是16字节代码。PLT[0]是一个特殊条目,它跳转到动态链接器中。每个被可执行程序调用的库函数都有它自己的PLT条目。每个条目都负责调用一个具体的函数。
<libc-2.27.so!__libc_start_main>
5.8 本章小结
第6章 hello进程管理
6.1 进程的概念与作用
进程的创建方法:在shell中,当用户运行新程序时,系统会调用fork复制与当前shell进程相同的一份资源给新程序,然后调用execve装载程序资源。
6.2 简述壳Shell-bash的作用与处理流程
shell的处理流程包括:解析指令、执行指令序列(调用系统函数)、打印执行结果信息。
6.3 Hello的fork进程创建过程
6.4 Hello的execve过程
execve函数在当前进程的上下文当中加载并且运行一个新的程序。
execve函数加载并运行可执行目标文件filename,且带参数列表argv和环境变量envp。只有当出现错误的时候,才会返回到调用的程序。execve调用一次从不返回。
6.5 Hello的进程执行
6.6 hello的异常与信号处理
信号可以被进程阻塞(延迟接收处理)、忽略、捕获并自定义处理或执行默认处理行为。
hello程序执行的过程中会遇到四类异常:中断,陷阱,故障和终止。
中断是来自于I/O设备的异步信号,内核调用中断处理程序进行处理,函数返回到当前指令的下一条代码进行继续执行。
陷阱是有意的异常,比如读写文件操作。是同步异常,调用陷阱处理程序进行相应的处理,处理程序后总是饭hi到当前指令的下一条指令继续进行执行。
终止是不可恢复的致命错误造成的结果,通常是一些硬件错误。终止处理程序将控制返回给一个abort例程,该例程将会终止这个应用程序。
Unix Shell使用job这个抽象概念来表示对一条命令行求值而创建的进程。
给单一进程发送:kill -信号ID PID(少一个负号-)
2、通过调用系统函数kill:kill(PID, SIGINT);
sigprocmask函数及其辅助函数可以明确地阻塞/解除阻塞选定的信号。
·sigaddset——把指定的信号signum添加到set中
在键盘上输入Ctrl+c会导致内核发送一个SIGINT信号到前台进程组的每个进程,默认情况是终止前台作业,用job查看没有hello进程。
6.7 本章小结
第7章 hello的存储管理
7.1 hello的存储器地址空间
结合hello说明逻辑地址、线性地址、虚拟地址、物理地址的概念。
虚拟地址(Virtual Address):CPU通过生成虚拟地址访问主存,这个虚拟地址在被送到内存之前先转换成适当的物理地址。Hello可执行目标程序中的地址就是虚拟内存地址。
7.2 Intel逻辑地址到线性地址的变换-段式管理
段式管理中,线性地址就是虚拟地址,程序从逻辑地址直接转换为虚拟地址。
在段式管理地址变换的过程中间,需要位运行的进程建立一个段表。
段表组成:段号、段长、存储权限、状态、起始地址、修改位、增补位
7.3 Hello的线性地址到物理地址的变换-页式管理
线性地址被划分为固定长度的组,成为页。每页包括4KB-4GB字节的地址空间。为了方便叙述,假设48位虚拟地址空间被划分为4KB的页,而每个页表条目都是4字节。
为了节约页表所占用的内存空间,x86-64将线性地址空间通过页目录表和页表多级查找转换成为物理地址。
7.4 TLB与四级页表支持下的VA到PA的变换
TLB利用VPN进行寻址,分为组索引(TLBI)和标记(TLBT),用来区别可能映射到同一个TLB组的不同的VPN。
为压缩页表,我们使用层次结构的多级页表。下图以一个两级页表层次结构为例,显示页表的层次结构组成。
以下以Core i7的地址翻译为例,介绍TLB和四级页表支持下的VA到PA的变换。
PT:页表、PTE:页表条目、VPN:虚拟页号、VPO:虚拟页偏移、PPN:物理页号、PPO:物理页偏移量
7.5 三级Cache支持下的物理内存访问
数据回写(write-back):这是最高性能的模式,也是最典型的,在回写模式下,cache内容更改不需要每次都写回内存,直到一个新的 cache要刷新或软件要求刷新时,才写回内存。
7.6 hello进程fork时的内存映射
7.7 hello进程execve时的内存映射
(1)删除已存在的用户区域。删除shell虚拟地址的用户部分中的已存在的区域结构。
(3)映射共享区域。如果hello程序与共享对象(或目标)链接,比如标准C 库libc. so, 那么这些对象都是动态链接到这个程序的,然后再映射到用户虚拟地址空间中的共享区域内。
(4)设置程序计数器(PC) 。execve 做的最后一件事情就是设置当前进程上下文中的程序计数器,使之指向hello代码区域的入口点。
7.8 缺页故障与缺页中断处理
缺页故障:内存不命中成为缺页。当指令引用一个虚拟地址,而与该地址相对应的物理页面不在内存中,因此必须从磁盘中取出时,就会发生故障。
7.9 动态存储分配管理
Printf会调用malloc,请简述动态内存管理的基本方法与策略。
隐式分配器:也叫做垃圾收集器,自动释放未使用的已分配的块的过程叫做垃圾收集。例如,诸如Lisp,ML,Java之类的高级语言就依赖垃圾收集来释放已分配的块。
1. 记录空闲块:显示空闲链表,隐式空闲链表。分离的空闲链表
7.10 本章小结
第8章 hello的IO管理
8.1 Linux的IO设备管理方法
输入输出(I/O)是在主存和外部设备之间复制数据的过程。输入操作是从I/O设备复制数据到主存,输出操作是从主存复制数据到I/O设备。
一个linux文件就是一个m个字节的序列:B0,B1,…,Bk,…,Bm-1
8.2 简述Unix IO接口及其函数
3.改变当前的文件位置。对于每个打开的文件,内核保持着一个文件位置k, 初始为0。这个文件位置是从文件开头起始的字节偏移量。应用程序能够通过执行seek操作,显式地设置文件的当前位置为K 。
1.进程是通过调用open 函数来打开一个已存在的文件或者创建一个新文件的:intopen(char *filename, int flags, mode_t mode);
3.应用程序是通过分别调用read 和write 函数来执行输入和输出的。
ssize_tread(int fd, void *buf, size_t n);
read函数从描述符为fd 的当前文件位置复制最多n 个字节到内存位置buf 。返回值-1表示一个错误,而返回值0 表示EOF。否则,返回值表示的是实际传送的字节数量。
返回:若成功则为读的字节数,若EOF 则为0, 若出错为-1。
ssize_twrite(int fd, const void *buf, size_t n);
write函数从内存位置buf 复制至多n 个字节到描述符fd 的当前文件位置。图10-3 展示了一个程序使用read 和write 调用一次一个字节地从标准输入复制到标准输出。
8.3 printf的实现分析
[转]printf 函数实现的深入剖析 - Pianistx - 博客园
int printf(const char *fmt, ...) {
va_list arg = (va_list)((char*)(&fmt)+4);
首先,arg得到第一个参数的起始地址。接下来调用vsprintf生成显示信息
1. intvsprintf(char *buf, const char *fmt, va_list args)
17. itoa(tmp, *((int*)p_next_arg));
vsprintf函数:作用为格式化,接受确定输出格式的格式字符串fmt。用格式字符串对个数变化的参数进行格式化输出,其返回值为要打印的字符串长度,即write中的i。
这里传递几个参数给寄存器,以一个int结束,int INT_VECTOR_SYS_CALL表示要通过系统来调用sys_call这个函数。接下来是到陷阱-系统调用 syscall。
6. push ebx //要打印的buf字符数组中的第一个元素
7. call [sys_call_table + eax * 4] //不断打印字符,直到遇到’\0’
10. mov [esi + EAXREG - P_STACKBASE], eax
当字符显示驱动子程序,从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)后,显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析
8.5 本章小结
结论
(1)编写hello程序:通过编辑器将hello的代码输入到计算机中并保存为hello.c文件。
(2)预处理:通过命令cpp hello.c > hello.i将 hello.c 调用的所有外部的库展开合并到一个 hello.i 文件中
(3)编译:通过命令gcc -Shello.i -o hello.s将 hello.i 编译成为汇编文件 hello.s
(4)汇编:通过命令as hello.s -o hello.o将 hello.s 会变成为可重定位目标文件 hello.o
(5)链接:通过一系列的命令将 hello.o 与可重定位目标文件和动态链接库链接成为可执行目标程序 hello
(6)运行:在 shell 中输入./hello 120L022115 王炳轩
(7)创建子进程:shell 进程调用 fork 为其创建子进程
(8)加载程序:shell 调用 execve,execve 调用启动加载器,加映射虚拟内存,进入程序入口后程序开始载入物理内存,然后进入 main 函数。
(9)程序的运行过程:如果运行途中键入 ctr-c ctr-z 则调用 shell 的信号处理函数分别停止、挂起。
(10)资源回收:shell 父进程回收子进程,内核删除为这个进程创建的所有数据结构。
附件
列出所有的中间产物的文件名,并予以说明起作用。
文件名 |
作用 |
hello.c |
程序源代码 |
hello.i |
hello.c经预处理之后得到的程序文件 |
hello.s |
hello.i文件经编译后得到的汇编语言源代码文件 |
hello.o |
hello.s文件经汇编后得到的可重定位目标文件 |
hello |
hello.o文件经过链接后得到的可执行目标文件 |
hello.o.objdump.txt |
hello.o的反汇编代码 |
hello.objdump.txt |
hello的反汇编代码 |
参考文献
[1] printf函数的实现剖析:https://www.cnblogs.com/pianist/p/3315801.html
[2] x86的四种地址:https://www.cnblogs.com/bhlsheji/p/4868964.html
;https://blog.csdn.net/rabbit_in_android/article/details/49976101
[3] gcc编译的四个步骤:https://blog.csdn.net/xiaohouye/article/details/52084770
[4] gcc -s的分析:http://blog.chinaunix.net/uid-20508657-id-1939444.html
[5] ELF格式分析:https://blog.csdn.net/edonlii/article/details/8779075
[6] 兰德尔E.布莱恩特 大卫R.奥哈拉伦.深入理解计算机系统(第三版).机械工业出版社.2018.4.
[7] C语言预处理命令详解:
https://blog.csdn.net/qq_40757240/article/details/88763441
[8] Pianistx:printf函数的深入剖析:https://www.cnblogs.com/pianist/p/3315801.html
[9] 段式管理:
段式管理_weixin_30421525的博客-CSDN博客
[10] 李忠,王晓波,余洁著. x86汇编语言 从实模式到保护模式. 北京:电子工业出版社, 2013.01.
[11] 吴锐. 计算机系统课程PPT, 哈尔滨工业大学, 2022.
哈工大计算机系统2022大作业:程序人生-Hello‘s P2P相关推荐
- 【2022】哈工大计算机系统大作业——程序人生Hello’s P2P
2022哈工大计算机系统大作业--程序人生Hello's P2P 摘要 第1章 概述 1.1 Hello简介 1.2 环境与工具 1.3 中间结果 1.4 本章小结 第2章 预处理 2.1 预处理的概 ...
- HIT 深入理解计算机系统 大作业 程序人生-Hello’s P2P
HIT 深入理解计算机系统 大作业 程序人生-Hello's P2P 本论文旨在研究 hello 在 linux 系统下的整个生命周期.结合 CSAPP 课本, 通过 gcc 等工具进行实验,从而将课 ...
- HITICSAPP2019大作业——程序人生-Hello’s P2P
俺是Hello,额是每一个 程序猿 ¤的初恋(羞羞--)却在短短几分钟后惨遭每个菜鸟的无情抛弃(呜呜--),他们很快喜欢上sum.sort.matrix.PR.AI.IOT.BD.MIS--,从不回头 ...
- 哈工大计算机系统2022年秋程序人生大作业
哈尔滨工业大学计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机科学与技术 学 号 2021112558 班 级 2103101 学 ...
- 哈工大2022春计算机系统大作业:程序人生-Hello‘s P2P
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机类 学 号 120L021305 班 级 2003002 学 生 李一凡 指 导 教 ...
- 2022计算机系统大作业——程序人生-Hello’s P2P
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机 学 号 120L021716 班 级 2003005 学 生 蔡泽栋 指 导 ...
- 哈工大 计算机系统大作业 程序人生-Hello’s P2P From Program to Process
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算学部 学 号 120L020512 班 级 2003004 学 生 黄鹏程 指 导 ...
- 2022春 计算机系统大作业 程序人生-Hello’s P2P
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算学部 学 号 班 级 学 生 指 导 教 师 计算机科学与技术学院 2022年5月 摘 要 为深入理解计算机系统,本文以hel ...
- 哈工大计算机系统大作业-程序人生-Hello’s P2P
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机科学与技术 学 号 2021110802 班 级 21w0312 学 生 黄键树 ...
最新文章
- 三相滤波器怎么接线_您知道家用电表如何接线吗?小编来告诉你!
- 第一天学习Android的一些笔记
- 一个完整的DS1302时钟在STM32上的应用实例
- 使用Base64进行string的加密和解密
- Linux kernel分析前的准备
- 根据条件查询某条记录的条数_「性能与架构」MySQL 8 查询优化新工具 Explain Analyze...
- python中re模块_python中re模块的使用以及一些正则表达式的总结
- C. 防止E-mail注入
- 常见异常代码oracle
- XCode 快捷键, MAC 快捷键
- oracle包写入程序失败_Oracle内核技术揭秘第一篇
- ViceDinoSpecCtrl.cpp
- MySQL报错 Packet for query is too large,server向mysql发送的数据包大小超过mysql限制
- php 分表 实战,PHP实战:1亿条数据如何分表100张到Mysql数据库中(PHP)
- JSONObject没有fromObject方法及其依赖引入
- Skyline软件二次开发初级——9如何在WEB页面中的三维地图上进行交互
- 94页5万字市级应急平台建设方案
- 谈一谈今年的移动互联网寒冬
- Reader/Writer字符流概述和使用方法
- 中国移动、联动、电信