汇编
任务格式。不同的处理器语法不一样。但都是在描述 操作什么任务,所以有指令,对象(source),被操作对象(destination)。 一般是这种格式 operator source destination,结果一般放到目标里面
表明操作字节大小 有些可以推导出来的会省略 不能 指令会加一些长度后缀 比如mov movl
数据表示方法,地址 值,
寄存器的用途,分为通用,和特殊用途。 用来计算,用来函数返回值的
这个是我自己总结的,可能既不完善也不准确
这是x86的指令CS107 Guide to x86-64
命令不懂查查说明书就会了,会有些看似多余的汇编指令,有一些不知道规则,可以搜一搜stackoverflow
分区
程序分为代码区,全局区、常量区、栈区、堆区
后面要用的寄存器
代码区
程序编译完生成很多条汇编指令,这些指令放在代码区,汇编每段指令都有一条地址如下图
全局区
static 、全局区变量,编译期数据应该就放到全局区,
常量区
放常量的
栈区
gcc gdb调试看汇编,每个函数汇编后大致结构
push %rbp
mov %rsp %rbp;
sub $0xN %rsp(N是一个数)
..........
add $0xN %rsp
pop %rbp
ret
在调用一个函数时候,会在当前函数栈帧下面生成一个下一个栈帧。函数调用的时候,call命令会把返回地址压入栈, push rbp把调用者的rbp压入栈,再把栈顶指针rsp赋给rbp,既在当前栈帧顶点作为起点建立一个新的栈帧,sub $0N %rsp给栈帧开辟空间的,rsp变成当前栈帧顶,rbp是栈底,再根据rbp作为相对地址,给局部变量和参数分配空间,末尾,add $0N %rsp ,把栈帧空间回收 ,栈弹出一个值(调用函数的rbp)给rbp,ret是pop+ jump指令,把返回地址弹出栈放eip然后执行这个地址指令。
所以栈区不需要手动释放,机制在那。
堆区
int* p3 =new int [1] ;
*p3 =7;
delete p3;
return 0;
mov $0x4,%ecx ,ecx第四个参数
callq 0x401610<_Znay> 分配堆
下一句 mov %rax -0x8(%rbq) %rax用来放函数返回值的,-0x8(%rbq)放的是分配地址,
%rax应该也是专门用来放地址的寄存器 ,这转来转去-0x8(%rbp)值给%rax, $0x7赋给(%rax)
0x00000000004015e9 <+27>: mov -0x8(%rbp),%rax
0x00000000004015ed <+31>: movl $0x7,(%rax)
0x00000000004015f3 <+37>: mov -0x8(%rbp),%rax
delete汇编
0x00000000004015f7 <+41>: mov $0x4,%edx
0x00000000004015fc <+46>: mov %rax,%rcx
0x00000000004015ff <+49>: callq 0x401618 <_ZdlPvy>
edx 是放第3个参数,应该是内存大小,rcx是放第4个参数应该是内存地址,然后调用callq 0x401618 <_ZdlPvy>
int* p=new int[4]
delete p
int* p=new int[4]
delete[] p
区别在这,求分配大小,然后如果为0就跳转就不执行这个delete函数
0x00000000004015f3 <+37>: cmpq $0x0,-0x8(%rbp)
0x00000000004015f8 <+42>: je 0x401606 <main()+56>
new完会返回一个指向堆内存的指针,不加delet没有机制会帮你去处理回收内存,所以需要手动释放。delete应该是默认类型大小删除,delete会去求分配大小,然后去删除