本系列主要根据<<汇编语言 第二版>>、<<揭秘JVM虚拟机-JVM设计原理与实现>>、<<Primer c++ 第五版>>等书籍的总结。对于《Primer c++》主要就是了解一些对java来说不同的语法,并没有深入研究,同时(前面两本书对于汇编指令的操作源与操作目标的表示是反过来的例如mov 指令的两个参数)。
一、计算机寄存器、机器指令相关介绍
1、计算机的0/1字节
对于计算机的处理来说,在内存的内容就是0/1二进制位,是没有指令与数据的区分的,而对于内存内容的区分要看其是指令还是内存就需要用到一些寄存器。
2、寄存器
1)、我们现在来梳理一下一些主要的寄存器
通用寄存器:AX、BX、CX等,这些是用来放一般性的数据的。
段寄存器(这个需要具体理解):CS&IP - 代码段寄存器&指令指针寄存器、SS&SP - 栈段寄存器&栈指针寄存器、DS - 数据段寄存器。
具体介绍:我们在前面说过内存中的内容是不能区分是指令还是数据的(都是0/1),所以就用寄存器来区分,送到CS&IP寄存器的就是指令(CPU从这里读取指令,然后通过流水线去解析、执行指令),然后也提供了SS&SP寄存器对于栈结构的支持。
这里再来说明下为什么需要使用到两个寄存器,因为CPU寻址使用了[基础地址+偏移地址=实际取内容的地址]这种设计,例如对于栈的分配,使用SS确定一个基础地址,然后将SP向下移动例如&0x10,这就表示这个栈的长度是16。由此也就可以理解段这个概念了,段就是一段连续的空间(人为定义的,内存本身划分并没有这个概念),我们可以将一段内存划分用来放指令,也可以划分一个栈空间。同时定义SS&SP来说,还有一个与它们一起使用的寄存器BS(基址指针寄存器),因为SP永远指向栈顶,所以有时候如果要取栈中的数据就使用BP,但其实这种解释并不是很好理解,也可以使用SP+偏移量来获取,看到后面应该就明白了(对于指令的调用可以看<<汇编语言 第二版>>的2.10章节)。
二、C程序的汇编、栈使用
1、C程序与对应汇编码
2、汇编过程解析(这个就简单说明,要具体了解分析可以看其他的文章了解)
这个是调用栈的划分,对于汇编指令来说,第一、二条是函数调用必定要调用的,将ebp(加e的表示是32位的寄存器)的内容入栈(这里可以简单理解,ebp的位置就是当前一个函数调用的栈低,而ESP指向的是真正的栈顶,当调用其他的函数完成后,要回到当前函数的栈顶,所以这个时候就需要用到EBP了。
两个栈之间还有的eip、ebp,我们知道CS:IP指向的是指令,因为我们调用到其他 函数去了其他函数的指令,所以这里就要记录下当前的函数的指令运行到哪里了,之后调用结束就将eip的值再送到EIP寄存器就能继续执行当前函数了。然后就sub 指令,就是将esp向下移32来划分一个栈空间。然后leave指令是表示返回,会对应主动加上两条指令(mov %ebp %esp、pop %eip),(这里的整个过程可以看<<揭秘JVM虚拟机-JVM设计原理与实现>>的2.1.1章节)
三、寄存器相关资料