<课堂笔记>
预备知识:
1.堆栈/栈: 如何被CPU维护,函数调用需要用到堆栈
2.寄存器:内存中的数据需要读入寄存器才能被CPU计算,
常用的寄存器EAX/EBX/ECX/EDX为通用寄存器
EBP:当前栈帧的开始处(若干函数调用形成一个堆栈,其中一个元素为一个栈帧)
ESP:指向函数栈的栈顶
EBP/ESP寄存器只有一个,函数调用需要保存现场就要把EBP入栈
3.GCC 汇编指令(ATT语法)
4.从硬盘到内存(进程的虚拟内存空间)
5.PUSH EBP 导致 ESP自动减4,栈生长,POP EBP导致 ESP+4,栈收缩
6.无法判断内存存放的是值还是地址,只有程序知道
高级语言实现及其汇编代码分析
C语言实现:
int demo(){ int x = 10; int y = 20; int sum = add(&x, &y); printf(“the sum is %d\n”,sum); return sum; }
int add(int *xp, int *yp){ int x = *xp; int y = *yp; return x+y; }
GCC 汇编
调用者demo
1 pushl %ebp //把ebp的值放到栈顶,同时esp-4,栈生长 2 movl %esp %ebp // 3 subl %24 esp //把esp值减去24个字节,相当于为函数分配了内存空间。ESP=776 4 movl $10 -4(%ebp) //$10表示立即数,把数字10存放到ebp值-4的内存地址中 5 movl $20 -8(%ebp) //把数字20存放到ebp值-8的内存地址中 //思考:变量名存放哪里? 在汇编中不需要变量名,所有操作都是针对地址和寄存器 6 leal -8(%ebp) %eax //把ebp存放的地址-8 放到 Eax寄存器,实际上就是指向 7 movl %eax 4(%esp) //把792 放到esp+4的内存地址 8 leal -4(%ebp) %eax 9 movl %eax (%esp) //6-9行实际上实现了对x,y的指针 10 call add //进入对add函数的调用 11 打印结果(略)--地址是100
被调用者函数add
1 push %ebp 2 movl %esp %ebp 3 pushl %ebx //保存现有的值,该存储器将要使用,intel约定,eax,ecx,edx寄存器调用者保存,ebx由被调用者保存 4 movl 8(%ebp) %edx //思考:到此edx的值是多少? ebp=768+8=776,addr776 value=796 5 movl 12(%ebp) %ecx //思考:到此ecx的值是多少? ebp=768+12=780,addr780 value=782 6 movl (%edx) %ebx //把ebx中地址的值放入ebx,根据地址从内存中取值 7 movl (%ecx) %eax //把ecx中地址的值放入eax,根据地址从内存中取值 8 add %ebx %eax 9 popl %ebx 10 popl %ebp 11 ret