[笔记] 汇编杂记(持续更新)
文章目录
- 前言
- 举例解释
- 函数的序言
- 函数的调用栈
- 数据的传递
- 总结
前言
举例解释
// Type your code here, or load an example.
int square(int num) {
return num * num;
}
int sub(int num1, int num2) {
return num1 - num2;
}
int add(int num1, int num2) {
return num1 + num2;
}
int divide(int num1, int num2) {
return num1 / num2;
}
int main() {
square(4);
sub(10,1);
add(1,1);
divide(16, 4);
return 0;
}
可使用 Compiler Explorer 在线转为汇编
对应的汇编:
square(int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov eax, DWORD PTR [rbp-4]
imul eax, DWORD PTR [rbp-4]
pop rbp
ret
sub(int, int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov DWORD PTR [rbp-8], esi
mov eax, DWORD PTR [rbp-8]
mov edx, DWORD PTR [rbp-4]
sub edx, eax
mov eax, edx
pop rbp
ret
add(int, int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov DWORD PTR [rbp-8], esi
mov eax, DWORD PTR [rbp-8]
mov edx, DWORD PTR [rbp-4]
add eax, edx
pop rbp
ret
divide(int, int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov DWORD PTR [rbp-8], esi
mov eax, DWORD PTR [rbp-4]
cdq
idiv DWORD PTR [rbp-8]
pop rbp
ret
main:
push rbp
mov rbp, rsp
mov edi, 4
call square(int)
mov esi, 1
mov edi, 10
call sub(int, int)
mov esi, 1
mov edi, 1
call add(int, int)
mov esi, 4
mov edi, 16
call divide(int, int)
mov eax, 0
pop rbp
ret
函数的序言
https://zhuanlan.zhihu.com/p/368962727
push rbp
mov rbp, rsp
...
pop rbp
sqaure前面的push rbp 和mov rbp, rsp又叫做函数的序言(prologue)
,几乎每个函数一开始都会有的指令。它和函数最后的pop rbp和ret(epilogue)起到维护函数的调用栈的作用。
函数的调用栈
数据的传递
数据的传递就分为以下四个方面
- 从内存到寄存器
- 从寄存器到内存
- 从立即数到寄存器,
- 从立即数到内存
注意:数据不能从内存直接传递到内存。如果需要从内存传递到内存,要以寄存器为中介。(这些知识,还是我当年大学学的计算机组成原理里面的)
- Intel的汇编会在数据前面说明数据大小,比如
mov DWORD PTR [rbp-4], 4
,意思是将一个4字节的4存储到 栈上(地址为rbp-4)。 - 而AT & T是通过指令的后缀来说明,同样的指令为
movl $4, -4(%rbp)
。而存储的地方,AT & T汇编是通过前缀来区别,比如%q前缀表示寄存器,$表示立即数,()表示内存。