0%

二进制基础

一、程序的编译与链接

从C源代码到可执行文件的生成过程

编译: 由C语言代码生成汇编代码

汇编: 由汇编代码生成机器码

链接 :将多个机器码的目标文件链接成一个可执行文件

1

​ C语言→汇编语言→机器码

二、Linux下的可执行文件格式

(1)什么是可执行文件?

广义:文件中的数据是可执行文件

例:

.out .exe .sh .py

狭义:文件中的数据是机器码的文件

例:

.out .exe .dll .so

.out .exe .dl .so

(2)可执行文件的分类

Windows:PE

可执行程序 动态链接库 静态链接库
.exe .dll .lib

Linux:ELF

可执行程序 动态链接库 静态链接库
.out .so .a

(3)磁盘中的ELF与内存中的ELF

磁盘中的储存方式:节

内存中的储存方式:段

2

RW可写 Data段 RX可读 Code段
.data .rodata
.bss .text
.got .int
.plt ELF Header
Stack Heap For Kernel STACK HEAP DATA CODE
用来管理函数调用的状态 申请动态内存的调用 操作系统代码 栈段 堆段 数据段 代码段

vmmap:查看程序进程的内存空间

注:数据从低地址向高地址写 Heap:是从低往高增长 Stack:是从高往低增长(栈的增长方向是相反的)

三、进程虚拟地址空间

3

(1)地址编码

地址以字节编码,1Byte=8bits,常以16进制表示

(2)二进制与十六进制转换

1.二进制转十六进制

例:11010110

从右往左每四位一组1101 0110,将二进制转换为十进制在对应为十六进制

1101=1×2³ + 1×2² + 0×2¹ + 1×2⁰ =13=D

0110=0×2³ + 1×2² + 1×2¹ + 0×2⁰=6

11010110=D6

2.十六进制转二进制

例:2AF

将每个十六进制的数转换为对应的四位二进制数,在组合起来

2=0010

A=10=1010

F=15=1111

2AF=0010 1010 1111

(3)虚拟内存

虚拟内存用户空间每个进程一份

虚拟内存内核空间所有进程共享一份

虚拟内存mmap段中的动态链接库仅在物理内存中装载一份

(4)段(segment)与节(section)

代码段(Text segment) 数据段(Data segment)
包含了代码与只读数据 包含了可读可写数据
.text 节 .data 节
.rodata 节 .dynamic 节
.hash 节 .got 节
.dynsym 节 .got.plt 节(保存plt节解析出的函数的实际地址)
.dynstr 节 .bss 节 (只占用内存的空间不占用磁盘的空间)
.plt 节(解析动态链接函数的实际地址)
.rel.got 节

(5)程序数据是如何在内存中组织的

image-20250114203349946

Data段:放已经初始化的全局变量

Bss段:放未初始化的全局变量

Text段:除了防止代码还放只读数据(.rodata)

Heap段:动态存储区

Stack段:存放局部变量(随着函数执行完被丢弃)

注:x,y是形参,当main函数调用sum函数时才会被用到,只有参数传递的时候才会被使用

32位架构:当main函数调用sum函数时,在创建sum函数的栈帧之前,将x和y的值压栈

64位架构:x,y不会放在虚拟内存中,而是放在寄存器中

(6)大端序与小端序

image-20250114212210896

小端序:低地址存放数据低位、高地址存放数据高位(大部分)

image-20250118180248328

大端序:低地址存放数据高位、高地址存放数据低位(小部分)

注:在C语言中0x00是字符串的结束符,大部分情况数据高位都为0,大端序低地址存放高位数据,数据是从低地址向高地址写,当进行溢出时,从低地址写入遇到0x00就直接结束了,所以小端序比大端序更好利用。

四、程序的装载与进程的执行

(1)进程的执行过程

image-20250114213905165

PC寄存器(Register):存放当前执行指令的地址(process count)

x86 eip x64 rip

(2)寄存器

image-20250114215650510

amd64位寄存器结构

名称 大小
rax 8Bytes
eax 4Bytes
ax 2Bytes
ah 1Bytes
al 1Bytes

部分寄存器的功能

名称 功能
RSP 存放当前栈帧的栈顶地址
RBP 存放当前栈帧的栈底地址
RAX 通用寄存器存放函数返回值
RIP 存放当前执行的指令的地址

(3)静态链接的程序的执行过程

image-20250114215750912

user mode:用户代码 hernel mode:操作系统代码

(4)动态链接的程序的执行过程

image-20250114231359629

五、x86&amd64汇编简述

(1)常用汇编指令

MOV LEA PUSH POP LEAVE RET
把源操作数传送给目标 把源操作数的有效地址送给指定的寄存器 把目标值压栈,同时SP指针-1字长 将栈顶的值弹出至目的存储位置,同时SP指针+1字长 在函数返回时,恢复父函数栈帧的指令 在函数返回时,控制程序执行流返回父函数的指令

(2)两种汇编格式

intel AT&T
mov eax, 8 movl $8, %eax
mov ebx, 0ffffh movl $0xffff, %ebx
int 80h int $80
mov eax, [ecx] movl (%ecx), %eax

image-20250207132728553

// 在最后添加