《深入理解计算机系统(第三版)》p164
1.运行时栈
C语言过程调用机制的一个关键特性在于使用了栈数据结构提供的后进先出的内存管理原则。
x86-64的栈向低地址方向增长,而栈指针%rsp指向栈顶元素。可以用pushq和popq指令将数据存入占中或是从栈中去除。将栈指针减少一个适当的量可以为没有指定初始值的数据在栈上分配空间。类似地,可以通过增加栈指针来释放空间。
当x86-64过程需要的存储空间超出寄存器能够存放的大小时,就会在栈上分配空间。这个部分称为过程的栈帧(stack farm)。

2.转移控制
3.数据传送
p168
x86-64中,可以通过寄存器最多传递6个整形(例如正数和指针)参数。寄存器的使用是有特殊顺序的,寄存器使用的名字取决于要传递的数据类型的大小。
如果一个函数有大于6个整型参数,超出6个的部分就要通过栈来传递。假设过程P调用过程Q,有n个整形参数,且n>6。那么P的代码分配的栈帧必须要能容纳7到n号参数的存储空间,如图3-25所示。要把参数1~6复制到对应的寄存器,把参数7~n放到栈上,而参数7位于栈顶。通过栈传递参数时,所有的数据大小都向8的倍数对齐。
参数到位以后,程序就可以执行call指令将控制转移到过程Q了。过程Q可以通过寄存器访问参数,有必要的话也可以通过栈访问。相应地,如果Q也调用了某个有超过6个参数的函数,它也需要在自己的栈帧中为超出6个部分的参数分配空间,如图3-25中标号为“参数构造区”的区域所示。
4.栈上的局部存储(不存在寄存器里的情况)
有些时候,局部数据必须存放在内存中,常见的情况包括:
(1)寄存器不足够存放所有的本地数据。
(2)对一个局部变量使用地址运算符&,因此必须能够为它产生一个地址。
(3)某些局部变量是数组或结构,因此必须能够通过数组或结构引用被访问到。
一般来说,过程通过减少栈指针在栈上分配空间。分配的结果作为栈帧的一部分,标号为“局部变量”,如图3-25所示。
汇编语言 -- lea和mov指令
1. mov
数据传送指令,目的操作数不能是立即数,数据不能从内存直接传送到内存(若需要,转化成2条指令,从内存取数据到寄存器,从寄存器到内存)
2. lea
lea(load effective address)其实是mov的变形,它的源操作数看上去是一个内存引用,但并非从指定位置读入数据,而是将有效地址写入到目的操作数,目的操作时只能为寄存器
-- 引自《深入理解计算机系统(第三版)》P129
寄存器名:实际上是访问寄存器内保存的数;eg: %rdi,实际上就是访问%rdi寄存器内保存的值
(寄存器名):实际上是以寄存器内存的值作为内存地址,访问该内存位置上存储的值eg: (%rdi),实际上就是访问以%rdi寄存器内的值作为内存地址的该位置存放的值
-- 引自 https://blog.csdn.net/weixin_42072410/article/details/102948676
mov指令与lea指令相反,一个是读取内存数据,一个是读取内存地址,例如:movq $4, 17(%rsp) 是指把数据4作为到 17(%rsp)所在内存的值(store 4 in &x4)。
加载有效地址(load effective address)指令就是lea,他的指令形式就是从内存读取数据到寄存器,但是实际上他没有引用内存,而是将有效地址写入到目的的操作数,就像是C语言地址操作符&一样的功能,可以获取数据的地址。例如 char x4 = 4;
例如:leaq 17(%rsp),%rax 是指把17(%rsp)的内存地址写入到%rax寄存器中(create &x4)。
(%rsp)表示%rsp这个寄存器里存的是内存地址,然后加括号表示去取这个内存地址里的值。