0x00 汇编语言是什么 我们知道,CPU 只负责计算,本身不具备智能。你输入一条指令它就运行一次,然后停下来,等待下一条指令。这些指令都是二进制的,称为操作码(opcode)也就是机器指令,比如加法指令就是00000011。编译器的作用,就是将高级语言写好的程序,翻译成一条条CPU能够读懂的机器指令然后传给CPU执行。对于人类来说,二进制程序是不可读的,根本看不出来机器干了什么。为了解决可读性的问题,以及偶尔的编辑需求,就诞生了汇编语言。
0x01 汇编语言的应用领域
汇编语言的优点是能够直接访问计算机硬件,所以执行起来要比那些高级语言效率高,而且占用资源极少,一般用于:系统内核、工业控制、驱动程序、实时系统、核心算法等对运行效率有极高要求的领域,或者说为了突破系统性能的瓶颈而将频繁使用的子程序或程序段用汇编来编写。
因为汇编语言是一种面向机器的语言,其汇编指令与机器指令基本上一一对应,所以汇编指令就和机器指令一样功能单一且具体,例如想要机算(A+B+C)那么我们就必须细化的安排CPU要进行运算的每一步(先计算A+B,然后把C与前者运算的结果相加),而且编写汇编语言程序时要考虑资源的限制,所以使用汇编语言开发程序对程序员的编程水平要求极高,而且开发程序的周期特别特别长,为了实现一个简单的功能都得非常的麻烦,所以现在已经很少有人编写纯汇编的应用程序了,但是我们学习CTF逆向不需要把汇编学到能开发大型应用程序的境界,我们的目的是读懂汇编,理解它的特性。因为汇编语言本身就是机器指令的一种符号表示,不同类型的CPU有不同的机器指令系统,所以汇编语言也有不同的类型,本文主要介绍的是目前最常见的也就是Intel CPU使用的x86汇编语言。
0x02 机器语言、汇编语言、高级语言的关系
最早的计算机采用机器语言,这种语言直接用二进制数表示,通过直接输入二进制数,插拔电路板等实现,也就是传说中的只用0和1编程,这种“编程”很容易出错,每个命令都是通过查命令表实现,既然是通过“查表”实现的,那当然也可以让计算机来代替人查表实现了。于是就产生了汇编语言,所以我们可以认为机器语言和汇编语言二者就是等价的。后来人们发现,用汇编语言编某一功能的时候,连续一段代码都是相同或相似,于是就考虑用一句语言来代替这一段汇编语言,于是就产生了高级语言(C\C++等)。因此,所有高级语言都能转化成汇编语言,而所有汇编语言又可转化成机器语言。反之,所有机器语言也可以转成汇编语言(因为二者等价)。但并不是所有汇编语言都能转成高级语言。
0x03 认识寄存器
我们首先要搞清楚寄存器和内存不是一种东西,寄存器是在CPU中,内存在内存条中。寄存器的存取速度相当于内存的100倍左右。CPU本身只负责运算,不负责储存数据。数据一般都储存在内存之中,CPU 要用的时候就去内存读写数据。但是,CPU 的运算速度远高于内存的读写速度,为了避免被内存的读写速度拖慢,CPU 都自带一级缓存和二级缓存。CPU 缓存可以看作是读写速度较快的内存。但是,CPU 缓存还是不够快,另外数据在缓存里面的地址是不固定的,CPU 每次读写都要先寻址再读写,这样会拖慢速度。因此,除了缓存之外,CPU还自带了寄存器(Register),用来储存最常用的数据。也就是说,那些最频繁读写的数据(例如循环变量),都会放在寄存器里面,CPU优先读写寄存器,再由寄存器跟内存交换数据。寄存器不依靠地址区分数据,而依靠名称。每一个寄存器都有自己的名称,我们告诉 CPU 去具体的哪一个寄存器拿数据,这样的速度是最快的,所以寄存器被喻为CPU的零级缓存。 |