汇编指令push,mov,call,pop,leave,ret建立与释放栈的过程

您所在的位置:网站首页 汇编语言中mov是什么意思 汇编指令push,mov,call,pop,leave,ret建立与释放栈的过程

汇编指令push,mov,call,pop,leave,ret建立与释放栈的过程

2024-07-14 09:55| 来源: 网络整理| 查看: 265

栈内的数据

栈在汇编层面是辅助实现函数调用的,每个函数调用过程在栈中被抽象成一帧 ,在老式的32位CPU架构IA32中还有固定寄存器指向当前帧底部(下图中的0x100000f4,0x100000d8)。每帧内保存的数据为当前函数的局部变量,当前函数内调用其他函数的参数,寄存器状态(调用者与被调用者依据约定分别负责保存与恢复部分寄存器),上一帧底部地址(x86-64取消),当前函数返回后的指令地址,各组别数据的长度不定顺序固定。 在这里插入图片描述

高级语言中的栈结构有数据后进先出的性质,永远都是操作栈最顶层的数据。在汇编指令层面有一个**%rsp寄存器总是保存着栈顶的内存地址**,以此抽象出一个栈指针指向栈顶数据,利用汇编指令push与pop完成数据的入栈与出栈,push与pop负责将%rsp保存的内存地址中的数据移到目标地址,并对%rsp内的地址进行加减操作。

push 源数据 //push指令可以分解为两条更基本的汇编指令: //--sub $指针移动长度 %rsp //栈指下移 //--mov 源数据 (%rsp) //推入数据至栈顶 pop 目标地址 //pop指令等同于: //--mov (%rsp)目标地址 //数据出栈 //--add $指针移动长度 %rsp //指针上移

在这里插入图片描述 对栈内数据的访问依靠指针的相对位置,如根据帧指针的相对位置寻找当前函数参数(IA32),根据栈指针的相对位置获取当前局部变量。 与高级语言只可访问栈内数据不同,编译器可读写栈外数据,例如在栈外(指针下方)的位置先写入数据后再移动栈指针,在x86-64指令结构中,甚至还可对相对于栈指针地址低128位的内存空间进行读写。相对于编程语言中的栈,汇编层面限制较差,不是那么纯粹。

栈空间的分配与回收

调用一个函数不一定100%会对栈进行分配,出于速度与性能cpu会优先考虑只用寄存器组完成函数的运行,但如果涉及下面的情况则一般会进行栈的分配: 1,寄存器组无法储存所有的函数局部变量。(当前函数或与它调用的函数累计) 2,有些局部变量是数组或结构。 3,需要计算局部变量的内存地址。 4,有调用另一个函数且参数超过6个。

举例,假如有函数声明和调用如下:

func1(a,b) ... func2(2,2) ... return end func2(a,b) ... return end main() func1(1,1) end

以上代码在一个老式的IA32的栈中的分配时机大概图示:

在这里插入图片描述 以帧的角度看,调用一个函数既涉及当前帧的空间分配也涉及下一帧的空间分配。在当前帧,编译器需要分别push进两个参数和指令返回地址。在下一帧中push进上一帧的起始地址(x86-64不需要了),再根据函数内具体情况继续分配空间。 在语言层面,调用函数既会触发上面的操作,在汇编层面涉及以下几条指令:

call func1 push 源数据 //push等同于sub与mov的组合 //--sub $指针移动长度 %rsp //--mov 源数据 相对栈指针的内存地址

call指令会完成以下3个动作,1,更改PC(%rip寄存器,负责指向下一条指令的地址)为func1函数的第一条相关指令的地址。2,将栈指针向下移动8Bytes(x64)。3,向栈中推入指令call func1的下一条指令的内存地址。 如上文所说,push指令等同于subq+moveq,它们三个的使用与顺序比较灵活,编译器可自行决定。

在代码中,当一个函数return或所有代码行运行结束则会跳回调用该函数的下一行代码处,所有局部变量都会释放。在汇编层面(32位指令架构)中由以下三条指令实现:

mov 帧指针内保存的帧底地址 %rsp //栈指针上移动到帧指针处 pop 帧指针寄存器 //将上一帧帧底地址出栈 ret //将指令返回地址出栈

等同于:

leave ret

在x86-64中由于取消了帧指针,可以更简洁的化为以下两条指令:

add %rsp 偏移值 //栈指针上移到上一帧帧顶 ret

也等同于

leave ret

ret相当于pop %rip,将返回地址出栈到程序计数器。leave指令相当于对mov,pop(IA32)或add(x86-64)包了一层(除了可恢复栈指针外好像还可以恢复被调用者寄存器状态)。总而言之,编译器对运行时栈的分配与回收就是依靠栈帧指针的上下移动来完成(x86-64只依赖栈指针)。 在这里插入图片描述

参考: 深入理解计算机系统 第二版,第三版 R.E.Bryant

维护日志: 2020-1-12:重写



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3