call & stack
stack有两个动作,push放入栈,pop取出
push raxrsp寄存器永远指着栈顶部

- 将rsp减少
- 将内容从新的rsp开始放入
类似代码:
sub rsp, 8mov [rsp], rax在C/C++的编译风格,每次进入函数开始前会像上图一样分配一块适当大小的空间
rbp指向局部变量的顶端
先 push rbp 将原先的rbp保存起来,然后把rbp设为当前rsp,再把rsp减去要分配的空间大小
以上图来说明就是 rbp = rsp, rsp -= 0x8
在函数结束的最后做相反的动作把rsp加回来再 pop rbp 还原rbp成上一个地方的局部变量顶端地址
自己编写assembly不一定要使用C/C++的局部变量风格
pop rbx
pop的动作跟push相反
- 将rsp内容取出
- 将rsp增加
类似代码:
mov [rsp], rbxadd rsp, 8使用 call label 呼叫函数,和 jmp label 非常相似,差别是call结束会返回原本的下一行
call前我们需要手动将参数依序放入固定位置,rdi, rsi, rdx, rcx, r8, r9, push… 然后使用call
指令call可以拆分成以下两个动作
push ripjmp label将永远指向下一行指令位址的rip推入栈,然后jmp
接着执行完内容使用ret返回到原本的下一行继续执行,若有返回值请手动存入rax再做ret
ret一样可以拆分为下列动作
pop rip将之前的rip从栈取出并放入rip,程式会依照rip所指的地方执行