1.在一般情况下,代码分为text、data、以及bss、等节,并不会将code和data混在一起使用。
.text :存放code的节
.data:存放有初始值的全域变数
.bss:存放没有初始值得全域的变数
.rodata:存放只读资料的节
比如:
#include <stdio.h>
int i ; /.bss 节
char *hello = "hello world"; / char *hello .data 节, "hello world" .rodata 节
执行文件的格式会根据os的不同,而有所不同:linux - elf windows - pe
在二进制文件的开头会有一个magic number(魔数),方便让os判断类型档案
linux 下可以使用file来检视
在程序执行时,基本上会根据读写执行权限及特性来分为数个段
一般来说可以分为rodata、data、code、stack、heap等段
data:读写
code:读执行
stack:读写
heap:读写
一般情况下程序会在磁盘中,而处理器会通过一连串的过程来将程序映射到内存中执行。
执行流程:
程序执行流程:
在文件头中:记录着那些段应该映射到什么位置,以及段的读写权限;记录着那些节属于那些段;当程序映射时会根据权限的不同分成好几个段,一个段可以包含0到多个节。
磁盘中的程序.data .bss .got.plt (读写)节映射到虚拟内存 DATA VMA 中,.rodata .text .init ELF Header(读或者读执行) 映射到code vma中
binary 可执行二进制文件。
ld.so:载入elf所需的共享库,这部分记录在elf的DT_NEED中;初始化GOT和其他初始化操作。
在ld.so执行完后套转到_start开始执行程序,
_start将以下参数传给_libc_start_main:环境参数其实位置,main的位置(通常在第一个参数),.int,.fini(程序结束前的收尾工作)
_libc_start_main主要作用是执行.init main .fini exit退出程序
寄存器:通用寄存器:
RAX RBX RCX RDX RSI RDI 64位寄存器
EAX EBX ECX EDX ESI EDI 32位寄存器
AX BX CX DX SI DI 16位寄存器 ;
r8 r9 r10 r11 r12 r13 r14 r15 - 64 bit
r8d r9d r10d … - 32 bit r8w r9w r10w … -16 bit r8b r9b r10b … - 8 bit;
堆栈指针寄存器 RSP(64位,指向栈顶,RSP到函数参数范围称为该函数的堆栈框架 rbp后面就是return address )
基指针寄存器 RBP (64位,指向堆栈底部)
程序技术寄存器 RIP(指向程序当前的位置)
标志寄存器 eflags
段寄存器 cs ss ds es fs gs
push rax=sub rsp,8;mov [rsp],rax 注意,这里是栈顶指针减8,栈顶指针64位,说明一个内存单元是8字节,每次进出栈栈顶指针要加减8
lea指令是取有效地址指令:lea reg (必须是为通用寄存器RAX RBX RCX RDX RSI RDI ),mem(必须是存储单元,一般为操作数或者间址寄存器,RBX RBP RSI RDI) LEA AX,[BX][DI](j基址加变址寻址) LEA DX,DATA [BX][SI](相对基址加变址寻址)
LEA BX, 6[DI] 某数组含20个元素,每个元素占一个字节,序号为0~19。设DI指向数组开头处,把序号为6的元素的偏移地址送到BX中