浅谈汇编,认识汇编(一)
首先,做为一名编程语言的学习者,我认为很有必要,不定期的对一个阶段的学习进行个总结,这样也算是一个知识的梳理吧。所以我写了这个对之前学习的汇编进行一个总结。
初生牛犊,还希望大佬们多多包容,提出建议,相互学习。
认识汇编
计算机cpu能直接识别的就是机器语言,其机器指令用二进制表示,这种方式的执行效率非常高,但同时却有一个很明显的问题,也就是非常复杂,可读性非常差。
所以出现了汇编语言,用一些单词或者词组代替机器指令,提高了程序的可读性,也易编写。当然论可读易编写不及高级语言那样,不过高级语言还是要编译成汇编语言(中间代码)再编译成二进制可执行文件。所以对于经常用 Java,C#,C++,Python等高级编程语言写程序的我们来说,我们了解汇编有助于更好的理解计算机编程的原理和底层的东西,而且多学无害嘛。
一、要想很好的理解汇编并掌握一定的汇编技巧,一定得对计算机的基本组成有一定的了解,尤其是对cpu和寄存器,因为汇编的指令大部分是基于这的。
这里我以8086cpu为例,因为8086微处理器体现了简单微处理器的一般原理(这里需要知道一个微处理器所能执行的全部指令,就是这个微处理器的指令系统,cpu的型号不同,指令系统也不同,我觉得这也是汇编出现的原因之一吧)8086cpu可由两个逻辑单元组成,一个称为总线接口单元BIU,一个称为执行单元EU。
总线接口单元的任务是:
1.对存储器的访问,包括从存储器取出程序中的指令,暂存起来待用(每一条指令都是在每一个存储单元里存放,要通过物理地址去寻找该指令所对应存储单元的位置,才能取出里面的内容,地址会在稍后讲解)从存储器中读取运算所需要的数据或者把计算出来的中间结果和最后结果写入存储器。
2.通过总线与I/O进行传输
执行单元的任务是:
执行指令,进行算数逻辑运算,完成地址的计算,向总线接口单元传输所需要的结果数据和访问存储器存储单元所需要的地址并且管理寄存器。
可以看出两个是相互独立且相互合作的关系。
二、下面来认识下寄存器结构
8086cpu内部有14个16位寄存器,用于保存数据,指令和地址。
这里可以看到有数据寄存器,地址寄存器,控制寄存器和段寄存器四种,每一种都是一种类型,存储不同的内容,从图中你可以看出不同的寄存器有着不同的功能,如其中的地址寄存器组,从名字你就可以想到它里面主要存储的就是地址数据(16位的地址)他们通过不同的寻址方式计算出偏移地址,结合段寄存组里存储的段地址算出物理地址来寻找对应的存储单元位置。,而CX主要是用来存储程序中你的循环结构循环的次数,就好像我们C语言中的for循环或while循环它一共循环了6次,这个寄存器就存储的内容数值就是6。这里可能大家会注意到AX,BX,CX,DX这四个寄存器比较特殊,他可以分为8个寄存器,即这四个16位的可以分为8个8位的。说道这里,就详细说一下我们的地址和数据进制吧。
先说地址,每一个存储单元都有一个物理地址,可以理解成我每一个房间对有唯一的一个门牌号,物理地址就相当于门牌号。在cpu与存储器进行信息交换的时候,需要利用物理地址来查找所要访问的存储单元。物理地址是20位的二进制数表示,但我们的物理地址又可以分为段地址和偏移地址两部分组成,就像这样(段地址:偏移地址)这种表示形式称为逻辑地址,它经过某种计算可得到物理地址(物理地址= 段地址*10H + 偏移地址)H为16进制表示,这里可能就有人有疑问了,为什么我们要把物理地址在用这种形式表示呢,为什么还分成段地址和偏移地址呢。这就要提到我上头所说道的寄存器了,因为寄存器它是16位的(不包括那细分的8个8位,他们不能用于地址计算),也就是2^16=65536,从0-65535这个范围刚好是64KB,显然这是不够的,所以通过逻辑地址这种地址划分方式可以很好的将段地址(段寄存器里)和偏移地址(地址寄存器组)两个16位的组成一个20位,把64KB扩展成1MB。我们需要简单的知道段地址和偏移地址都有相应的寄存器存储。
下面一张图大家更好的理解物理地址和逻辑地址。
下面两张图方便理解存储单元和地址作用