关于栈空间大小
反汇编代码中的栈大小
- 栈帧的大小通常是由编译器在编译阶段计算出来的。
- 编译器在编译源代码时会分析函数的局部变量、函数参数、寄存器的使用情况等信息,然后根据这些信息计算出每个函数所需的栈帧大小。
自己写汇编
- 需要自己计算栈帧的大小,并为局部变量、参数、寄存器保存等分配适当的空间。
- 需要考虑以下几个方面:
- 确定函数内部定义的局部变量的大小和数量,以及函数的参数的大小和传递方式(寄存器还是栈传递)。【超过6个参数,就需要在栈上分配空间】
- 如果函数在执行过程中使用了寄存器来保存临时值,您需要决定是否需要将这些寄存器的值保存到栈上。
- 确保分配的栈空间满足目标架构的对齐要求,以避免内存访问错误。
- 根据需要,您可能需要在栈帧中分配一些额外的空间来处理异常或存储调试信息。
- 编写正确的栈操作指令,包括分配和释放栈空间,以及在函数调用和返回时恢复栈帧状态。
关于push等操作
push
- 这个操作会将arg里面的值入栈
- 而rsp寄存器,则会减少相应的字节数,自动指向栈顶
- 由高地址向低地址
1 |
push arg |
pop
- 这个操作会将栈顶保存的值出栈,并将值存入arg里面
- 而rsp寄存器,则会增加相应的字节数,自动指向新的栈顶
- 由低地址向高地址
- 需要明确一点,
pop arg
并不是用来恢复rsp
的操作。- 它是用来将栈顶的值出栈,存储到目标操作数
arg
中
- 它是用来将栈顶的值出栈,存储到目标操作数
1 |
pop arg |
关于栈的位置
- 汇编里操作的栈和进程的地址空间的栈区是关联的
- 但是,在汇编里操作寄存器和内存地址,通常是需要特定的指令来操作的
操作寄存器
- 对寄存器执行操作时(如
push
、pop
、mov
等指令),是在直接对寄存器中的值进行操作,而不涉及内存地址。
访问内存地址
- 要访问内存中的数据,需要使用相应的内存寻址方式
- 在汇编语言中,可以使用
- 基址寻址
- 变址寻址
- 立即数寻址等方式来访问内存地址
相对定位
- 操作栈时,栈顶位置通常由栈指针
rsp
控制 - 使用
sub rsp, <value>
或add rsp, <value>
指令可以相对于当前的rsp
值对栈进行操作- 从而实现对栈帧的调整。通过这种方式,您可以分配和释放栈空间,存取局部变量等
CPU,寄存器,汇编的栈,内存,进程
寄存器
- 寄存器是CPU里面存储器
进程
- 在现代操作系统中,每个进程都有自己的虚拟地址空间,其中包括代码、数据、堆、栈等区域。
- 进程的栈区实际上是这个虚拟地址空间中的一部分,用于存储局部变量、函数调用信息以及函数的返回地址等。
内存
- 操作系统通过内存管理单元(
Memory Management Unit
,MMU
)将进程的虚拟地址映射到物理内存,从而实现了地址空间的隔离和保护 - 当 CPU 执行进程时,
MMU
负责将进程的虚拟地址映射到物理内存的实际位置- CPU执行汇编指令实际上是在物理内存中进行的
- 这样,CPU 实际上并不需要准确地定位到进程的栈区,而是通过虚拟地址和物理地址的映射关系来访问进程的栈区数据
汇编的栈
- 在汇编语言中,栈是一个抽象的概念,表示一种后进先出(LIFO)的数据结构,用于存储临时数据和函数调用的上下文信息
- 在汇编指令中,
push
和pop
操作是在栈上执行的,通过操作栈指针rsp
来分配和释放栈空间,并在栈上存取数据 - 汇编代码中的栈操作是在虚拟内存中执行的
- 栈是位于进程的内存地址空间中的一块区域
- 在内存中通常是从高地址向低地址生长的
- 栈的底部通常位于较高的内存地址,而栈的顶部位于较低的内存地址
- 通过
push
和pop
指令来执行栈操作,实际上是在虚拟内存中对栈区进行读写操作 - CPU在虚拟地址空间中执行栈操作,而实际的数据读写发生在物理内存中的栈区
执行
- CPU通过内存管理单元(
MMU
)将汇编指令要达成的操作映射到进程的内存地址空间(虚拟内存),包括栈区空间- 这样,汇编代码中的栈操作实际上是在进程的栈区空间中进行的
- 通过
MMU
这种映射,CPU可以在虚拟地址空间中执行指令和访问数据,而实际的数据读写发生在物理内存中
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ X86_64汇编学习记述四08/09
- ♥ 寄存器03/27
- ♥ 汇编记述二08/07
- ♥ 基础知识03/22
- ♥ x86_64汇编学习记述一08/06
- ♥ 关于程序03/29