通用寄存器
RAX
- 是一个 64 位寄存器,可以存储 64 位的数据。
RAX
寄存器在 x86 架构中广泛用于存储操作数、函数返回值以及执行算术和逻辑操作。它是通用寄存器,可以用于多种目的。- 调用约定:
- 在函数调用中,
RAX
寄存器通常用于存储函数的返回值。 - 根据不同的调用约定,可能还有其他寄存器用于存储返回值,但
RAX
是最常用的寄存器之一。
- 在函数调用中,
- 扩展:
RAX
寄存器可以在需要时扩展为 128 位或更大的寄存器,如RAX-EAX-AX-AH-AL
。rax
-64eax
-rax
低32位ax
-eax
低16位ah
-ax
高8位al
-ax
低8位
EBX
- 基址寄存器,通常用于存储内存地址。
ECX
- 计数器寄存器,用于循环计数和一般计数操作。
EDX
- 数据寄存器,常用于存储数据和执行一般算术运算。
ESI
- 源变址寄存器,通常用于存储源数据地址。
EDI
- 目标变址寄存器,通常用于存储目标数据地址。
ESP
- 栈指针寄存器,用于管理栈操作。
- 在函数调用时,会使用
sub rsp, <size>
指令分配局部变量的空间,从而rsp
减小,为局部变量腾出位置。 - 当函数返回时,会使用
leave
或mov rsp, rbp
恢复栈帧,将rsp
的值重新调整到原来的位置。
EBP
- 基址指针寄存器,通常用于指向栈帧的基址。
- 在函数调用时,通常会将调用函数的
rbp
值保存在栈中,然后将当前的rsp
赋值给rbp
,从而建立新的栈帧。
段寄存器
CS
- 代码段寄存器,用于存储代码段的选择子。
DS
- 数据段寄存器,用于存储数据段的选择子。
SS
- 堆栈段寄存器,用于存储堆栈段的选择子。
ES- FS- GS
- 附加段寄存器,可用于存储其他数据段的选择子。
标志寄存器
EFLAGS
- 用于存储和控制各种条件和状态标志,如进位标志、零标志、溢出标志等。
指令寄存器
EIP
- 存储当前正在执行的指令的地址。
浮点寄存器
FPU
- 用于执行浮点数运算。
- 包括多个浮点寄存器
ST0
、ST1
、ST2
等。
寄存器代码理解
1 |
push rbp |
- 将堆栈帧的基址指针压入栈
- 栈向下扩展
- 不断存入各个函数的堆栈帧的基址指针
- 栈寄存器自动指向栈顶,也就是最新的
rbp
- 也就是说,这个所谓的栈里面保存的是整个函数调用链路上的各个函数的堆栈帧的基址指针
1 2 |
push rbp mov rbp, rsp |
- 第一条指令见如上
- 第二条指令是将当前栈顶的值赋值给
rbp
寄存器- 实际上是在这个函数的入口建立了一个新的堆栈帧
- 函数执行结束后,通常使用
pop rbp
将之前保存的rbp
值出栈- 同时,
rsp
恢复到调用函数时的状态
- 同时,
1 2 |
pop rbp ret |
- 使用这个指令来恢复栈帧,它会恢复上一个函数的基址指针
rbp
的值leave
相当于上面的组合
- 它会将
rbp
的值赋给rsp
,然后将之前保存的rbp
值出栈,恢复外部环境
1 |
aa: .zero 1 |
.zero
用于在目标文件中分配一定数量的字节并初始化为零aa:
是一个标签(label),.zero 1
表示在标签aa
处分配一个字节的空间,并将该字节的值初始化为零。
1 2 |
; 将一个值存储到分配的空间中 mov BYTE PTR [aa], 42 |
- 将值
42
存储到了分配的字节空间中
1 2 3 4 |
aa: .zero 1 mov BYTE PTR [aa], 42 mov BYTE PTR [aa], 84 |
- 最终这个空间的内容就会是
84
,因为第二次的存储操作覆盖了第一次的值。
1 2 3 4 5 6 7 |
.section .data aa: .zero 4 .text mov DWORD PTR [aa], 22 mov DWORD PTR [aa+4], 33 mov DWORD PTR [aa+8], 44 mov DWORD PTR [aa+12], 55 |
- 分配4个字节大小的空间,并挨个赋值
1 |
sub rsp, 16 |
- 表示将栈指针
rsp
减去16
字节,这通常用于为当前函数的局部变量分配内存空间。
参数相关
- 常见的 x86-64 调用约定是使用以下寄存器来传递函数参数:
rdi
: 第一个参数rsi
: 第二个参数rdx
: 第三个参数rcx
: 第四个参数r8
: 第五个参数r9
: 第六个参数
- 如果函数的参数个数超过了这些寄存器的数量,额外的参数会被保存在栈上。
进程地址空间相关介绍
- 以下由高地址向低地址:
内核空间
- 用途:存储操作系统内核的代码和数据。
- 属性:不同于用户空间,通常具有更高的特权级别,可以直接访问硬件。
- 增长方向:通常不适用于用户进程的内存管理。
共享库段
- 用途:存储共享库(动态链接库)的代码和数据。
- 属性:可读写,通常具有执行权限。
- 增长方向:正向(向高地址增长)。
栈段
- 用途:存储局部变量、函数参数、返回地址等,由系统自动管理。
- 属性:可读写,通常不可执行。
- 增长方向:反向(向低地址增长)。
堆段
- 用途:动态分配的内存块,由程序员手动管理(例如使用
malloc
、new
等)。 - 属性:可读写。
- 增长方向:正向(向高地址增长),但在一些系统中也可以向低地址增长。
BSS段
- 用途:存储未初始化的全局和静态变量,它们在程序开始执行之前会被操作系统初始化为零。
- 属性:可读写。
- 增长方向:正向(向高地址增长)。
数据段
- 用途:存储已初始化的全局和静态变量。
- 属性:可读写。
- 增长方向:正向(向高地址增长)。
代码段
- 用途:存储程序的可执行指令。
- 代码段中存储的指令是CPU可以直接执行的二进制指令
- 这些指令是编写程序的算法和逻辑的具体实现
- 属性:只读,通常具有执行权限。
- 增长方向:正向(向高地址增长)。
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ 汇编记述三08/07
- ♥ 汇编记述二08/07
- ♥ X86_64汇编学习记述四08/09
- ♥ x86_64汇编学习记述二08/07
- ♥ X86_64汇编学习记述三08/08
- ♥ 基础知识03/22